[eigen] boost::multiprecision : wrong eigen values |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
Dear All,
in case you are interested, I've attached an example where the eigen values using
boost::multiprecision are wrong. In addition, in contrast to the documentation,
they are not sorted, which could be a hint for the problem.
I included a Makefile, which provides executables for double, long double, boost::multiprecision and mpfr.
All, except boost::multiprecision, are consistent. As you can also realize, boost::multiprecision is
much slower compared to mpfr, so I'm not using it and I have no need for it to be fixed.
However, it might be interesting to see, why it fails.
In case you wonder how I come up with the matrix, it's just an example I found in an application of mine.
Best regards,
Peter
#include <stdlib.h>
#include <iostream>
#include <cmath>
#include <Eigen/Dense>
#include <algorithm>
// --------------------
#if defined( D_boost )
// --------------------
#include <boost/multiprecision/cpp_bin_float.hpp>
#define MyBoost_Prec 500
const int MyBoostPrec2 = MyBoost_Prec * log(2.0)/log(10.0) ;
typedef boost::multiprecision::cpp_bin_float< MyBoostPrec2 > mp_backend; ///< Why is it using decimal precision???
typedef boost::multiprecision::number<mp_backend, boost::multiprecision::et_off> TpFloat;
// courtesy of Carsten Daniel Burgard
// we have to turn off expression templates to make Eigen like boost
// this is apparently needed because multiprecision doesn't come with an int() operator
namespace Eigen {
namespace internal {
template<typename NewType>
struct cast_impl<TpFloat,NewType> {
static inline NewType run(const TpFloat& x) {
return x.convert_to<NewType>();
}
};
}
}
// --------------------
#elif defined( D_mpfr )
// --------------------
#include <unsupported/Eigen/MPRealSupport>
typedef mpfr::mpreal TpFloat;
// --------------------
#elif defined( D_ld )
// --------------------
typedef long double TpFloat;
// --------------------
#elif defined ( D_d )
// --------------------
typedef double TpFloat;
#endif
// ------------------------------------------------------------
typedef Eigen::Matrix< TpFloat, Eigen::Dynamic, 1> TpVector;
typedef Eigen::Matrix< TpFloat, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> TpMatrix;
typedef Eigen::Array< TpFloat , Eigen::Dynamic, 1> TpArray;
int main( const int argc, const char *argv[] )
{
const int dim = 32;
TpMatrix H( dim, dim );
TpArray E,EE;
int Precision = (argc>1) ? atoi(argv[1]) : 500 ;
#if defined( D_boost )
Precision = MyBoost_Prec;
#elif defined( D_mpfr )
mpfr::mpreal::set_default_prec(Precision);
#else
Precision = 8 * sizeof( TpFloat );
#endif
H << -0.125, -0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0, -0.7071067812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, -0.125, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0, 0, 0, -0.7071067812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, -0, -0.125, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0, 0, 0, -0.7071067812, 0, 0, 0, 0, 0, 0, 0,
-0, -0, -0, -0.125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0, -0.7071067812, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -0.125, -0, -0, -0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -0, -0.125, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -0, -0, -0.125, -0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -0, -0, -0, -0.125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -0.125, -0, -0, -0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -0, -0.125, -0, -0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0.125, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0.125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0.7071067812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0, 0,
0, -0.7071067812, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0.7071067812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7071067812, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, -0.7071067812, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7071067812, 0,
0, -0.7071067812, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0,
0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, -0.7071067812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, -0.7071067812, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7071067812, 0,
0, 0, 0, -0.7071067812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7071067812,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0, 0.7071067812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.375, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0, 0, 0, -0.7071067812, 0, 0, 0, 0, 0, 0, 0, 0, 0.375, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7071067812, 0, 0, 0, 0, 0.7071067812, 0, 0, 0, 0, 0, 0.375, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7071067812, 0, 0, 0.7071067812, 0, 0, 0, 0, 0, 0.375;
Eigen::SelfAdjointEigenSolver<TpMatrix> eigensolverH;
eigensolverH.compute( H );
EE =eigensolverH.eigenvalues().array();
std::sort( EE.data(), EE.data() + dim ); // needed for mp-boost, should be sorted according to docs.
E = EE - EE(0);
std::cout << E.transpose() << std::endl;
return 0;
}
CFLAGS=-O3 -march=native -DNDEBUG
All: MpTest_d MpTest_ld MpTest_mpfr MpTest_boost
clean:
rm -f MpTest_d MpTest_ld MpTest_mpfr MpTest_boost
MpTest_d: MpTest.C
g++ -DD_d $(CFLAGS) MpTest.C -I $(HOME)/Eigen/eigen -o MpTest_d
MpTest_ld: MpTest.C
g++ -DD_ld $(CFLAGS) MpTest.C -I $(HOME)/Eigen/eigen -o MpTest_ld
MpTest_mpfr: MpTest.C
g++ -DD_mpfr $(CFLAGS) MpTest.C -I $(HOME)/Eigen/eigen -I $(HOME)/Eigen/eigen/unsupported/test/mpreal -l mpfr -o MpTest_mpfr
MpTest_boost: MpTest.C
g++ -DD_boost $(CFLAGS) MpTest.C -I $(HOME)/Eigen/eigen -I $(HOME)/RG/Boost/boost-stable -o MpTest_boost