1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef EIGEN_POLYNOMIAL_SOLVER_H
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_POLYNOMIAL_SOLVER_H
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace Eigen {
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \ingroup Polynomials_Module
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *  \class PolynomialSolverBase.
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * \brief Defined to be inherited by polynomial solvers: it provides
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * convenient methods such as
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *  - real roots,
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *  - greatest, smallest complex roots,
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *  - real roots with greatest, smallest absolute real value,
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *  - greatest, smallest real roots.
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * It stores the set of roots as a vector of complexes.
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate< typename _Scalar, int _Deg >
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass PolynomialSolverBase
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Deg==Dynamic ? Dynamic : _Deg)
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef _Scalar                             Scalar;
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef typename NumTraits<Scalar>::Real    RealScalar;
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef std::complex<RealScalar>            RootType;
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef Matrix<RootType,_Deg,1>             RootsType;
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef DenseIndex Index;
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template< typename OtherPolynomial >
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void setPolynomial( const OtherPolynomial& poly ){
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_roots.resize(poly.size()); }
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template< typename OtherPolynomial >
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline PolynomialSolverBase( const OtherPolynomial& poly ){
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      setPolynomial( poly() ); }
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline PolynomialSolverBase(){}
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns the complex roots of the polynomial */
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RootsType& roots() const { return m_roots; }
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Clear and fills the back insertion sequence with the real roots of the polynomial
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * i.e. the real part of the complex roots that have an imaginary part which
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * absolute value is smaller than absImaginaryThreshold.
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * absImaginaryThreshold takes the dummy_precision associated
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * with the _Scalar template parameter of the PolynomialSolver class as the default value.
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[out] bi_seq : the back insertion sequence (stl concept)
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[in]  absImaginaryThreshold : the maximum bound of the imaginary part of a complex
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *  number that is considered as real.
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * */
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename Stl_back_insertion_sequence>
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void realRoots( Stl_back_insertion_sequence& bi_seq,
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      using std::abs;
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      bi_seq.clear();
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for(Index i=0; i<m_roots.size(); ++i )
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if( abs( m_roots[i].imag() ) < absImaginaryThreshold ){
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          bi_seq.push_back( m_roots[i].real() ); }
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename squaredNormBinaryPredicate>
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RootType& selectComplexRoot_withRespectToNorm( squaredNormBinaryPredicate& pred ) const
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index res=0;
867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      RealScalar norm2 = numext::abs2( m_roots[0] );
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for( Index i=1; i<m_roots.size(); ++i )
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        const RealScalar currNorm2 = numext::abs2( m_roots[i] );
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if( pred( currNorm2, norm2 ) ){
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          res=i; norm2=currNorm2; }
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return m_roots[res];
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /**
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \returns the complex root with greatest norm.
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     */
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RootType& greatestRoot() const
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::greater<Scalar> greater;
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return selectComplexRoot_withRespectToNorm( greater );
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /**
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \returns the complex root with smallest norm.
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     */
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RootType& smallestRoot() const
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::less<Scalar> less;
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return selectComplexRoot_withRespectToNorm( less );
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename squaredRealPartBinaryPredicate>
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RealScalar& selectRealRoot_withRespectToAbsRealPart(
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        squaredRealPartBinaryPredicate& pred,
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        bool& hasArealRoot,
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
1227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      using std::abs;
123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      hasArealRoot = false;
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index res=0;
125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      RealScalar abs2(0);
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for( Index i=0; i<m_roots.size(); ++i )
128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
1297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if( abs( m_roots[i].imag() ) < absImaginaryThreshold )
130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          if( !hasArealRoot )
132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          {
133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            hasArealRoot = true;
134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            res = i;
135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            abs2 = m_roots[i].real() * m_roots[i].real();
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          }
137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          else
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          {
139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            const RealScalar currAbs2 = m_roots[i].real() * m_roots[i].real();
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            if( pred( currAbs2, abs2 ) )
141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            {
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              abs2 = currAbs2;
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              res = i;
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            }
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          }
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        else
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
1497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          if( abs( m_roots[i].imag() ) < abs( m_roots[res].imag() ) ){
150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            res = i; }
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
1537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return numext::real_ref(m_roots[res]);
154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename RealPartBinaryPredicate>
158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RealScalar& selectRealRoot_withRespectToRealPart(
159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        RealPartBinaryPredicate& pred,
160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        bool& hasArealRoot,
161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
1637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      using std::abs;
164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      hasArealRoot = false;
165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index res=0;
166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      RealScalar val(0);
167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for( Index i=0; i<m_roots.size(); ++i )
169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
1707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if( abs( m_roots[i].imag() ) < absImaginaryThreshold )
171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          if( !hasArealRoot )
173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          {
174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            hasArealRoot = true;
175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            res = i;
176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            val = m_roots[i].real();
177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          }
178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          else
179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          {
180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            const RealScalar curr = m_roots[i].real();
181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            if( pred( curr, val ) )
182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            {
183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              val = curr;
184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              res = i;
185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            }
186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          }
187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        else
189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
1907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          if( abs( m_roots[i].imag() ) < abs( m_roots[res].imag() ) ){
191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            res = i; }
192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
1947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return numext::real_ref(m_roots[res]);
195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /**
199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \returns a real root with greatest absolute magnitude.
200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * A real root is defined as the real part of a complex root with absolute imaginary
201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * part smallest than absImaginaryThreshold.
202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * absImaginaryThreshold takes the dummy_precision associated
203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * with the _Scalar template parameter of the PolynomialSolver class as the default value.
204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * If no real root is found the boolean hasArealRoot is set to false and the real part of
205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * the root with smallest absolute imaginary part is returned instead.
206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *
207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[out] hasArealRoot : boolean true if a real root is found according to the
208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *  absImaginaryThreshold criterion, false otherwise.
209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[in] absImaginaryThreshold : threshold on the absolute imaginary part to decide
210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *  whether or not a root is real.
211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     */
212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RealScalar& absGreatestRealRoot(
213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        bool& hasArealRoot,
214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::greater<Scalar> greater;
217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return selectRealRoot_withRespectToAbsRealPart( greater, hasArealRoot, absImaginaryThreshold );
218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /**
222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \returns a real root with smallest absolute magnitude.
223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * A real root is defined as the real part of a complex root with absolute imaginary
224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * part smallest than absImaginaryThreshold.
225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * absImaginaryThreshold takes the dummy_precision associated
226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * with the _Scalar template parameter of the PolynomialSolver class as the default value.
227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * If no real root is found the boolean hasArealRoot is set to false and the real part of
228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * the root with smallest absolute imaginary part is returned instead.
229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *
230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[out] hasArealRoot : boolean true if a real root is found according to the
231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *  absImaginaryThreshold criterion, false otherwise.
232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[in] absImaginaryThreshold : threshold on the absolute imaginary part to decide
233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *  whether or not a root is real.
234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     */
235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RealScalar& absSmallestRealRoot(
236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        bool& hasArealRoot,
237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::less<Scalar> less;
240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return selectRealRoot_withRespectToAbsRealPart( less, hasArealRoot, absImaginaryThreshold );
241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /**
245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \returns the real root with greatest value.
246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * A real root is defined as the real part of a complex root with absolute imaginary
247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * part smallest than absImaginaryThreshold.
248c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * absImaginaryThreshold takes the dummy_precision associated
249c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * with the _Scalar template parameter of the PolynomialSolver class as the default value.
250c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * If no real root is found the boolean hasArealRoot is set to false and the real part of
251c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * the root with smallest absolute imaginary part is returned instead.
252c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *
253c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[out] hasArealRoot : boolean true if a real root is found according to the
254c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *  absImaginaryThreshold criterion, false otherwise.
255c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[in] absImaginaryThreshold : threshold on the absolute imaginary part to decide
256c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *  whether or not a root is real.
257c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     */
258c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RealScalar& greatestRealRoot(
259c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        bool& hasArealRoot,
260c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
261c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
262c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::greater<Scalar> greater;
263c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return selectRealRoot_withRespectToRealPart( greater, hasArealRoot, absImaginaryThreshold );
264c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
265c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
266c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
267c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /**
268c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \returns the real root with smallest value.
269c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * A real root is defined as the real part of a complex root with absolute imaginary
270c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * part smallest than absImaginaryThreshold.
271c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * absImaginaryThreshold takes the dummy_precision associated
272c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * with the _Scalar template parameter of the PolynomialSolver class as the default value.
273c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * If no real root is found the boolean hasArealRoot is set to false and the real part of
274c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * the root with smallest absolute imaginary part is returned instead.
275c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *
276c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[out] hasArealRoot : boolean true if a real root is found according to the
277c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *  absImaginaryThreshold criterion, false otherwise.
278c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     * \param[in] absImaginaryThreshold : threshold on the absolute imaginary part to decide
279c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     *  whether or not a root is real.
280c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     */
281c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const RealScalar& smallestRealRoot(
282c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        bool& hasArealRoot,
283c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const
284c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
285c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::less<Scalar> less;
286c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return selectRealRoot_withRespectToRealPart( less, hasArealRoot, absImaginaryThreshold );
287c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
288c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
289c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
290c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    RootsType               m_roots;
291c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
292c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
293c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES( BASE )  \
294c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename BASE::Scalar                 Scalar;       \
295c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename BASE::RealScalar             RealScalar;   \
296c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename BASE::RootType               RootType;     \
297c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename BASE::RootsType              RootsType;
298c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
299c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
300c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
301c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \ingroup Polynomials_Module
302c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
303c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \class PolynomialSolver
304c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
305c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \brief A polynomial solver
306c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
307c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * Computes the complex roots of a real polynomial.
308c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
309c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \param _Scalar the scalar type, i.e., the type of the polynomial coefficients
310c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \param _Deg the degree of the polynomial, can be a compile time value or Dynamic.
311c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *             Notice that the number of polynomial coefficients is _Deg+1.
312c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
313c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * This class implements a polynomial solver and provides convenient methods such as
314c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * - real roots,
315c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * - greatest, smallest complex roots,
316c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * - real roots with greatest, smallest absolute real value.
317c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * - greatest, smallest real roots.
318c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
319c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * WARNING: this polynomial solver is experimental, part of the unsuported Eigen modules.
320c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
321c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
322c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * Currently a QR algorithm is used to compute the eigenvalues of the companion matrix of
323c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * the polynomial to compute its roots.
324c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * This supposes that the complex moduli of the roots are all distinct: e.g. there should
325c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * be no multiple roots or conjugate roots for instance.
326c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * With 32bit (float) floating types this problem shows up frequently.
327c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * However, almost always, correct accuracy is reached even in these cases for 64bit
328c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * (double) floating types and small polynomial degree (<20).
329c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  */
330c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate< typename _Scalar, int _Deg >
331c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass PolynomialSolver : public PolynomialSolverBase<_Scalar,_Deg>
332c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
333c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
334c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Deg==Dynamic ? Dynamic : _Deg)
335c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
336c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef PolynomialSolverBase<_Scalar,_Deg>    PS_Base;
337c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES( PS_Base )
338c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
339c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef Matrix<Scalar,_Deg,_Deg>                 CompanionMatrixType;
340c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef EigenSolver<CompanionMatrixType>         EigenSolverType;
341c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
342c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
343c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Computes the complex roots of a new polynomial. */
344c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template< typename OtherPolynomial >
345c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void compute( const OtherPolynomial& poly )
346c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
3477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert( Scalar(0) != poly[poly.size()-1] );
348c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      internal::companion<Scalar,_Deg> companion( poly );
349c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      companion.balance();
350c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_eigenSolver.compute( companion.denseMatrix() );
351c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_roots = m_eigenSolver.eigenvalues();
352c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
353c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
354c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
355c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template< typename OtherPolynomial >
356c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline PolynomialSolver( const OtherPolynomial& poly ){
357c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      compute( poly ); }
358c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
359c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline PolynomialSolver(){}
360c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
361c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
362c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    using                   PS_Base::m_roots;
363c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EigenSolverType         m_eigenSolver;
364c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
365c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
366c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
367c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate< typename _Scalar >
368c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass PolynomialSolver<_Scalar,1> : public PolynomialSolverBase<_Scalar,1>
369c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
370c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
371c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef PolynomialSolverBase<_Scalar,1>    PS_Base;
372c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES( PS_Base )
373c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
374c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
375c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Computes the complex roots of a new polynomial. */
376c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template< typename OtherPolynomial >
377c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void compute( const OtherPolynomial& poly )
378c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
3797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert( Scalar(0) != poly[poly.size()-1] );
380c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_roots[0] = -poly[0]/poly[poly.size()-1];
381c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
382c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
383c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
384c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    using                   PS_Base::m_roots;
385c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
386c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
387c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace Eigen
388c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
389c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif // EIGEN_POLYNOMIAL_SOLVER_H
390