00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00148
00149
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
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
00177 VERIFY( internal::isApprox( roots.array().abs().maxCoeff(),
00178 internal::abs( psolve.greatestRoot() ), psPrec ) );
00179
00180
00181 VERIFY( internal::isApprox( roots.array().abs().minCoeff(),
00182 internal::abs( psolve.smallestRoot() ), psPrec ) );
00183
00184 bool hasRealRoot;
00185
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
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
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
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 }