polynomialsolver.cpp
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #include "main.h"
11 #include <unsupported/Eigen/Polynomials>
12 #include <iostream>
13 #include <algorithm>
14 
15 using namespace std;
16 
17 namespace Eigen {
18 namespace internal {
19 template<int Size>
21 {
22  enum {
23  ret = (Size == Dynamic) ? Dynamic : Size+1
24  };
25 };
26 }
27 }
28 
29 
30 template<int Deg, typename POLYNOMIAL, typename SOLVER>
31 bool aux_evalSolver( const POLYNOMIAL& pols, SOLVER& psolve )
32 {
33  typedef typename POLYNOMIAL::Index Index;
34  typedef typename POLYNOMIAL::Scalar Scalar;
35 
36  typedef typename SOLVER::RootsType RootsType;
37  typedef Matrix<Scalar,Deg,1> EvalRootsType;
38 
39  const Index deg = pols.size()-1;
40 
41  // Test template constructor from coefficient vector
42  SOLVER solve_constr (pols);
43 
44  psolve.compute( pols );
45  const RootsType& roots( psolve.roots() );
46  EvalRootsType evr( deg );
47  for( int i=0; i<roots.size(); ++i ){
48  evr[i] = std::abs( poly_eval( pols, roots[i] ) ); }
49 
50  bool evalToZero = evr.isZero( test_precision<Scalar>() );
51  if( !evalToZero )
52  {
53  cerr << "WRONG root: " << endl;
54  cerr << "Polynomial: " << pols.transpose() << endl;
55  cerr << "Roots found: " << roots.transpose() << endl;
56  cerr << "Abs value of the polynomial at the roots: " << evr.transpose() << endl;
57  cerr << endl;
58  }
59 
60  std::vector<Scalar> rootModuli( roots.size() );
61  Map< EvalRootsType > aux( &rootModuli[0], roots.size() );
62  aux = roots.array().abs();
63  std::sort( rootModuli.begin(), rootModuli.end() );
64  bool distinctModuli=true;
65  for( size_t i=1; i<rootModuli.size() && distinctModuli; ++i )
66  {
67  if( internal::isApprox( rootModuli[i], rootModuli[i-1] ) ){
68  distinctModuli = false; }
69  }
70  VERIFY( evalToZero || !distinctModuli );
71 
72  return distinctModuli;
73 }
74 
75 
76 
77 
78 
79 
80 
81 template<int Deg, typename POLYNOMIAL>
82 void evalSolver( const POLYNOMIAL& pols )
83 {
84  typedef typename POLYNOMIAL::Scalar Scalar;
85 
86  typedef PolynomialSolver<Scalar, Deg > PolynomialSolverType;
87 
88  PolynomialSolverType psolve;
89  aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve );
90 }
91 
92 
93 
94 
95 template< int Deg, typename POLYNOMIAL, typename ROOTS, typename REAL_ROOTS >
96 void evalSolverSugarFunction( const POLYNOMIAL& pols, const ROOTS& roots, const REAL_ROOTS& real_roots )
97 {
98  using std::sqrt;
99  typedef typename POLYNOMIAL::Scalar Scalar;
100 
101  typedef PolynomialSolver<Scalar, Deg > PolynomialSolverType;
102 
103  PolynomialSolverType psolve;
104  if( aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve ) )
105  {
106  //It is supposed that
107  // 1) the roots found are correct
108  // 2) the roots have distinct moduli
109 
110  typedef typename POLYNOMIAL::Scalar Scalar;
111  typedef typename REAL_ROOTS::Scalar Real;
112 
113  //Test realRoots
114  std::vector< Real > calc_realRoots;
115  psolve.realRoots( calc_realRoots );
116  VERIFY( calc_realRoots.size() == (size_t)real_roots.size() );
117 
118  const Scalar psPrec = sqrt( test_precision<Scalar>() );
119 
120  for( size_t i=0; i<calc_realRoots.size(); ++i )
121  {
122  bool found = false;
123  for( size_t j=0; j<calc_realRoots.size()&& !found; ++j )
124  {
125  if( internal::isApprox( calc_realRoots[i], real_roots[j], psPrec ) ){
126  found = true; }
127  }
128  VERIFY( found );
129  }
130 
131  //Test greatestRoot
132  VERIFY( internal::isApprox( roots.array().abs().maxCoeff(),
133  abs( psolve.greatestRoot() ), psPrec ) );
134 
135  //Test smallestRoot
136  VERIFY( internal::isApprox( roots.array().abs().minCoeff(),
137  abs( psolve.smallestRoot() ), psPrec ) );
138 
139  bool hasRealRoot;
140  //Test absGreatestRealRoot
141  Real r = psolve.absGreatestRealRoot( hasRealRoot );
142  VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
143  if( hasRealRoot ){
144  VERIFY( internal::isApprox( real_roots.array().abs().maxCoeff(), abs(r), psPrec ) ); }
145 
146  //Test absSmallestRealRoot
147  r = psolve.absSmallestRealRoot( hasRealRoot );
148  VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
149  if( hasRealRoot ){
150  VERIFY( internal::isApprox( real_roots.array().abs().minCoeff(), abs( r ), psPrec ) ); }
151 
152  //Test greatestRealRoot
153  r = psolve.greatestRealRoot( hasRealRoot );
154  VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
155  if( hasRealRoot ){
156  VERIFY( internal::isApprox( real_roots.array().maxCoeff(), r, psPrec ) ); }
157 
158  //Test smallestRealRoot
159  r = psolve.smallestRealRoot( hasRealRoot );
160  VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
161  if( hasRealRoot ){
162  VERIFY( internal::isApprox( real_roots.array().minCoeff(), r, psPrec ) ); }
163  }
164 }
165 
166 
167 template<typename _Scalar, int _Deg>
168 void polynomialsolver(int deg)
169 {
170  typedef internal::increment_if_fixed_size<_Deg> Dim;
171  typedef Matrix<_Scalar,Dim::ret,1> PolynomialType;
172  typedef Matrix<_Scalar,_Deg,1> EvalRootsType;
173 
174  cout << "Standard cases" << endl;
175  PolynomialType pols = PolynomialType::Random(deg+1);
176  evalSolver<_Deg,PolynomialType>( pols );
177 
178  cout << "Hard cases" << endl;
179  _Scalar multipleRoot = internal::random<_Scalar>();
180  EvalRootsType allRoots = EvalRootsType::Constant(deg,multipleRoot);
181  roots_to_monicPolynomial( allRoots, pols );
182  evalSolver<_Deg,PolynomialType>( pols );
183 
184  cout << "Test sugar" << endl;
185  EvalRootsType realRoots = EvalRootsType::Random(deg);
186  roots_to_monicPolynomial( realRoots, pols );
187  evalSolverSugarFunction<_Deg>(
188  pols,
189  realRoots.template cast <
190  std::complex<
191  typename NumTraits<_Scalar>::Real
192  >
193  >(),
194  realRoots );
195 }
196 
198 {
199  for(int i = 0; i < g_repeat; i++)
200  {
201  CALL_SUBTEST_1( (polynomialsolver<float,1>(1)) );
202  CALL_SUBTEST_2( (polynomialsolver<double,2>(2)) );
203  CALL_SUBTEST_3( (polynomialsolver<double,3>(3)) );
204  CALL_SUBTEST_4( (polynomialsolver<float,4>(4)) );
205  CALL_SUBTEST_5( (polynomialsolver<double,5>(5)) );
206  CALL_SUBTEST_6( (polynomialsolver<float,6>(6)) );
207  CALL_SUBTEST_7( (polynomialsolver<float,7>(7)) );
208  CALL_SUBTEST_8( (polynomialsolver<double,8>(8)) );
209 
210  CALL_SUBTEST_9( (polynomialsolver<float,Dynamic>(
211  internal::random<int>(9,13)
212  )) );
213  CALL_SUBTEST_10((polynomialsolver<double,Dynamic>(
214  internal::random<int>(9,13)
215  )) );
216  CALL_SUBTEST_11((polynomialsolver<float,Dynamic>(1)) );
217  }
218 }
void evalSolver(const POLYNOMIAL &pols)
void test_polynomialsolver()
T poly_eval(const Polynomials &poly, const T &x)
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
Definition: LDLT.h:16
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const AbsReturnType abs() const
void roots_to_monicPolynomial(const RootVector &rv, Polynomial &poly)
void evalSolverSugarFunction(const POLYNOMIAL &pols, const ROOTS &roots, const REAL_ROOTS &real_roots)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:33
bool aux_evalSolver(const POLYNOMIAL &pols, SOLVER &psolve)
EIGEN_DEVICE_FUNC CastXpr< NewType >::Type cast() const
const int Dynamic
Definition: Constants.h:21
void polynomialsolver(int deg)


hebiros
Author(s): Xavier Artache , Matthew Tesch
autogenerated on Thu Sep 3 2020 04:08:37