polynomialsolver.cpp
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com>
00005 //
00006 // Eigen is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 3 of the License, or (at your option) any later version.
00010 //
00011 // Alternatively, you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License as
00013 // published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License and a copy of the GNU General Public License along with
00023 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00024 
00025 #include "main.h"
00026 #include <unsupported/Eigen/Polynomials>
00027 #include <iostream>
00028 #include <algorithm>
00029 
00030 #ifdef HAS_GSL
00031 #include "gsl_helper.h"
00032 #endif
00033 
00034 using namespace std;
00035 
00036 namespace Eigen {
00037 namespace internal {
00038 template<int Size>
00039 struct increment_if_fixed_size
00040 {
00041   enum {
00042     ret = (Size == Dynamic) ? Dynamic : Size+1
00043   };
00044 };
00045 }
00046 }
00047 
00048 
00049 template<int Deg, typename POLYNOMIAL, typename SOLVER>
00050 bool aux_evalSolver( const POLYNOMIAL& pols, SOLVER& psolve )
00051 {
00052   typedef typename POLYNOMIAL::Index Index;
00053   typedef typename POLYNOMIAL::Scalar Scalar;
00054 
00055   typedef typename SOLVER::RootsType    RootsType;
00056   typedef Matrix<Scalar,Deg,1>          EvalRootsType;
00057 
00058   const Index deg = pols.size()-1;
00059 
00060   psolve.compute( pols );
00061   const RootsType& roots( psolve.roots() );
00062   EvalRootsType evr( deg );
00063   for( int i=0; i<roots.size(); ++i ){
00064     evr[i] = std::abs( poly_eval( pols, roots[i] ) ); }
00065 
00066   bool evalToZero = evr.isZero( test_precision<Scalar>() );
00067   if( !evalToZero )
00068   {
00069     cerr << "WRONG root: " << endl;
00070     cerr << "Polynomial: " << pols.transpose() << endl;
00071     cerr << "Roots found: " << roots.transpose() << endl;
00072     cerr << "Abs value of the polynomial at the roots: " << evr.transpose() << endl;
00073     cerr << endl;
00074   }
00075 
00076   #ifdef HAS_GSL
00077   if (internal::is_same< Scalar, double>::value)
00078   {
00079     typedef GslTraits<Scalar> Gsl;
00080     RootsType gslRoots(deg);
00081     Gsl::eigen_poly_solve( pols, gslRoots );
00082     EvalRootsType gslEvr( deg );
00083     for( int i=0; i<gslRoots.size(); ++i )
00084     {
00085       gslEvr[i] = std::abs( poly_eval( pols, gslRoots[i] ) );
00086     }
00087     bool gslEvalToZero = gslEvr.isZero( test_precision<Scalar>() );
00088     if( !evalToZero )
00089     {
00090       if( !gslEvalToZero ){
00091         cerr << "GSL also failed" << endl; }
00092       else{
00093         cerr << "GSL did NOT failed" << endl; }
00094       cerr << "GSL roots found: " << gslRoots.transpose() << endl;
00095       cerr << "Abs value of the polynomial at the GSL roots: " << gslEvr.transpose() << endl;
00096       cerr << endl;
00097     }
00098   }
00099   #endif //< HAS_GSL
00100 
00101 
00102   std::vector<Scalar> rootModuli( roots.size() );
00103   Map< EvalRootsType > aux( &rootModuli[0], roots.size() );
00104   aux = roots.array().abs();
00105   std::sort( rootModuli.begin(), rootModuli.end() );
00106   bool distinctModuli=true;
00107   for( size_t i=1; i<rootModuli.size() && distinctModuli; ++i )
00108   {
00109     if( internal::isApprox( rootModuli[i], rootModuli[i-1] ) ){
00110       distinctModuli = false; }
00111   }
00112   VERIFY( evalToZero || !distinctModuli );
00113 
00114   return distinctModuli;
00115 }
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 template<int Deg, typename POLYNOMIAL>
00124 void evalSolver( const POLYNOMIAL& pols )
00125 {
00126   typedef typename POLYNOMIAL::Scalar Scalar;
00127 
00128   typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;
00129 
00130   PolynomialSolverType psolve;
00131   aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve );
00132 }
00133 
00134 
00135 
00136 
00137 template< int Deg, typename POLYNOMIAL, typename ROOTS, typename REAL_ROOTS >
00138 void evalSolverSugarFunction( const POLYNOMIAL& pols, const ROOTS& roots, const REAL_ROOTS& real_roots )
00139 {
00140   typedef typename POLYNOMIAL::Scalar Scalar;
00141 
00142   typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;
00143 
00144   PolynomialSolverType psolve;
00145   if( aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve ) )
00146   {
00147     //It is supposed that
00148     // 1) the roots found are correct
00149     // 2) the roots have distinct moduli
00150 
00151     typedef typename POLYNOMIAL::Scalar                 Scalar;
00152     typedef typename REAL_ROOTS::Scalar                 Real;
00153 
00154     typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;
00155     typedef typename PolynomialSolverType::RootsType    RootsType;
00156     typedef Matrix<Scalar,Deg,1>                        EvalRootsType;
00157 
00158     //Test realRoots
00159     std::vector< Real > calc_realRoots;
00160     psolve.realRoots( calc_realRoots );
00161     VERIFY( calc_realRoots.size() == (size_t)real_roots.size() );
00162 
00163     const Scalar psPrec = internal::sqrt( test_precision<Scalar>() );
00164 
00165     for( size_t i=0; i<calc_realRoots.size(); ++i )
00166     {
00167       bool found = false;
00168       for( size_t j=0; j<calc_realRoots.size()&& !found; ++j )
00169       {
00170         if( internal::isApprox( calc_realRoots[i], real_roots[j] ), psPrec ){
00171           found = true; }
00172       }
00173       VERIFY( found );
00174     }
00175 
00176     //Test greatestRoot
00177     VERIFY( internal::isApprox( roots.array().abs().maxCoeff(),
00178           internal::abs( psolve.greatestRoot() ), psPrec ) );
00179 
00180     //Test smallestRoot
00181     VERIFY( internal::isApprox( roots.array().abs().minCoeff(),
00182           internal::abs( psolve.smallestRoot() ), psPrec ) );
00183 
00184     bool hasRealRoot;
00185     //Test absGreatestRealRoot
00186     Real r = psolve.absGreatestRealRoot( hasRealRoot );
00187     VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
00188     if( hasRealRoot ){
00189       VERIFY( internal::isApprox( real_roots.array().abs().maxCoeff(), internal::abs(r), psPrec ) );  }
00190 
00191     //Test absSmallestRealRoot
00192     r = psolve.absSmallestRealRoot( hasRealRoot );
00193     VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
00194     if( hasRealRoot ){
00195       VERIFY( internal::isApprox( real_roots.array().abs().minCoeff(), internal::abs( r ), psPrec ) ); }
00196 
00197     //Test greatestRealRoot
00198     r = psolve.greatestRealRoot( hasRealRoot );
00199     VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
00200     if( hasRealRoot ){
00201       VERIFY( internal::isApprox( real_roots.array().maxCoeff(), r, psPrec ) ); }
00202 
00203     //Test smallestRealRoot
00204     r = psolve.smallestRealRoot( hasRealRoot );
00205     VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
00206     if( hasRealRoot ){
00207     VERIFY( internal::isApprox( real_roots.array().minCoeff(), r, psPrec ) ); }
00208   }
00209 }
00210 
00211 
00212 template<typename _Scalar, int _Deg>
00213 void polynomialsolver(int deg)
00214 {
00215   typedef internal::increment_if_fixed_size<_Deg>            Dim;
00216   typedef Matrix<_Scalar,Dim::ret,1>                  PolynomialType;
00217   typedef Matrix<_Scalar,_Deg,1>                      EvalRootsType;
00218 
00219   cout << "Standard cases" << endl;
00220   PolynomialType pols = PolynomialType::Random(deg+1);
00221   evalSolver<_Deg,PolynomialType>( pols );
00222 
00223   cout << "Hard cases" << endl;
00224   _Scalar multipleRoot = internal::random<_Scalar>();
00225   EvalRootsType allRoots = EvalRootsType::Constant(deg,multipleRoot);
00226   roots_to_monicPolynomial( allRoots, pols );
00227   evalSolver<_Deg,PolynomialType>( pols );
00228 
00229   cout << "Test sugar" << endl;
00230   EvalRootsType realRoots = EvalRootsType::Random(deg);
00231   roots_to_monicPolynomial( realRoots, pols );
00232   evalSolverSugarFunction<_Deg>(
00233       pols,
00234       realRoots.template cast <
00235                     std::complex<
00236                          typename NumTraits<_Scalar>::Real
00237                          >
00238                     >(),
00239       realRoots );
00240 }
00241 
00242 void test_polynomialsolver()
00243 {
00244   for(int i = 0; i < g_repeat; i++)
00245   {
00246     CALL_SUBTEST_1( (polynomialsolver<float,1>(1)) );
00247     CALL_SUBTEST_2( (polynomialsolver<double,2>(2)) );
00248     CALL_SUBTEST_3( (polynomialsolver<double,3>(3)) );
00249     CALL_SUBTEST_4( (polynomialsolver<float,4>(4)) );
00250     CALL_SUBTEST_5( (polynomialsolver<double,5>(5)) );
00251     CALL_SUBTEST_6( (polynomialsolver<float,6>(6)) );
00252     CALL_SUBTEST_7( (polynomialsolver<float,7>(7)) );
00253     CALL_SUBTEST_8( (polynomialsolver<double,8>(8)) );
00254 
00255     CALL_SUBTEST_9( (polynomialsolver<float,Dynamic>(
00256             internal::random<int>(9,13)
00257             )) );
00258     CALL_SUBTEST_10((polynomialsolver<double,Dynamic>(
00259             internal::random<int>(9,13)
00260             )) );
00261   }
00262 }


libicr
Author(s): Robert Krug
autogenerated on Mon Jan 6 2014 11:33:11