Registered Member
|
Hi,
I made a simple example to play with eigen's eigen value and eigen vector functionalities.
using g++-4.8.0, I get the following compiler error: In file included from /home/meng/libs/eigen-eigen-2249f9c22fe8/Eigen/Core:298:0, from /home/meng/libs/eigen-eigen-2249f9c22fe8/Eigen/Dense:1, from t.cc:4: /home/meng/libs/eigen-eigen-2249f9c22fe8/Eigen/src/Core/Block.h: In instantiation of ‘Eigen::Block<XprType, BlockRows, BlockCols, InnerPanel, true>::Block(XprType&, Eigen::Block<XprType, BlockRows, BlockCols, InnerPanel, true>::Index) [with XprType = const Eigen::CwiseUnaryView<Eigen::internal::scalar_real_ref_op<std::complex<double> >, Eigen::Matrix<std::complex<double>, -1, -1> >; int BlockRows = -1; int BlockCols = 1; bool InnerPanel = true; Eigen::Block<XprType, BlockRows, BlockCols, InnerPanel, true>::Index = long int]’: /home/meng/libs/eigen-eigen-2249f9c22fe8/Eigen/src/Core/../plugins/BlockMethods.h:560:34: required from ‘Eigen::DenseBase<Derived>::ConstColXpr Eigen::DenseBase<Derived>::col(Eigen::DenseBase<Derived>::Index) const [with Derived = Eigen::CwiseUnaryView<Eigen::internal::scalar_real_ref_op<std::complex<double> >, Eigen::Matrix<std::complex<double>, -1, -1> >; Eigen::DenseBase<Derived>::ConstColXpr = const Eigen::Block<const Eigen::CwiseUnaryView<Eigen::internal::scalar_real_ref_op<std::complex<double> >, Eigen::Matrix<std::complex<double>, -1, -1> >, -1, 1, true, true>; Eigen::DenseBase<Derived>::Index = long int]’ t.cc:13:10: required from here /home/meng/libs/eigen-eigen-2249f9c22fe8/Eigen/src/Core/Block.h:271:39: error: passing ‘const Eigen::CwiseUnaryView<Eigen::internal::scalar_real_ref_op<std::complex<double> >, Eigen::Matrix<std::complex<double>, -1, -1> >’ as ‘this’ argument of ‘Eigen::CwiseUnaryViewImpl<ViewOp, MatrixType, Eigen::Dense>::Scalar& Eigen::CwiseUnaryViewImpl<ViewOp, MatrixType, Eigen::Dense>::coeffRef(Eigen::CwiseUnaryViewImpl<ViewOp, MatrixType, Eigen::Dense>::Index, Eigen::CwiseUnaryViewImpl<ViewOp, MatrixType, Eigen::Dense>::Index) [with ViewOp = Eigen::internal::scalar_real_ref_op<std::complex<double> >; MatrixType = Eigen::Matrix<std::complex<double>, -1, -1>; Eigen::CwiseUnaryViewImpl<ViewOp, MatrixType, Eigen::Dense>::Scalar = double; Eigen::CwiseUnaryViewImpl<ViewOp, MatrixType, Eigen::Dense>::Index = long int]’ discards qualifiers [-fpermissive] : Base(internal::const_cast_ptr(&xpr.coeffRef( I read the definition of CwiseUnaryViewImpl in eigen-eigen-2249f9c22fe8/Eigen/src/Core/CwiseUnaryView.h and found that EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) does not have a const member overload which caused the error. I wonder is this intended or an overlook? Thanks. If this is an overlook, then similar problem also exists for the following member EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) Best Meng |
Moderator
|
This is the intended behavior. The problem is that EigenSolver<T> is expecting a non-qualified type for T, so in your case:
EigenSolver<MatrixXd> es(m); or play with std::remove_const |
Registered Member
|
|
Registered Member
|
I tried this method and it does not work. I also realized it should not work because by standard requirement, std::decay should have already removed any cv-qualifiers from its template argument type, which is to say typename std::decay<decltype(m)>::type is Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> already. To make sure this is the case, I added a static_assert to my sample code static_assert(std::is_same<typename std::decay<decltype(m)>::type, Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>>::value,""); and I did not see it's triggered for a compilation that produced the same error as I posted earlier, i.e., static_assert did not stop the compilation which is later stopped by the coeffRef issue. I also briefly read EigenSolver's compute method and I found it accepts const-qualified type regardless if the MatrixType is const-qualified, which makes sense to me because (I expect) the solver does not modify its argument. As far as I understand, further in the call chain, HessenbergDecomposition::compute makes a copy of the matrix before doing anything and later computation is based on the copy, which again makes sense to me, but this also suggests the const-qualifier (or absence) of the source type should not affect the solver as long as the solver is instantiated with a non-const qualified type, which is the case in my example. I think the real issue causing the compiler error in my example is this line auto const ex = es.eigenvectors().real(); because removing the const keyword in this declaration will make the program compile. However, I think the program should compile even at the presence of the const keyword because when all the related objects are const, it makes sense to expect the eigenvectors are also const types. Moreover, it is also dangerous to use a non-const eigenvectors because we then can accidentally modify its values. Therefore, the fact that CwiseUnaryViewImpl does not provide const overload for coeffRef member functions looks like an overlook to me because we should be able to read a const-qualified object (or expression). Based on my analysis, can you please reconsider my question? Thanks. |
Moderator
|
well, this does compile fine:
while it fails if you remove the std::remove_const. |
Moderator
|
Maybe this a bug of gcc as I cannot reproduce with clang and decay<T>::type should indeed be a simple alias for remove_cv<remove_reference<T>::type>::type
|
Registered Member
|
it compiles because you did not try to access its columns as I did in my example, i.e., this line causes the actual trouble when ex is declared const. ex.col(0); because it is in this line where the compiler has to access the data, hence necessitating the use of CwiseUnaryViewImpl::coeffRef. |
Moderator
|
ok, forget all the previous confusion. Actually it is very good thing it does not compile because if it would then you'd get random segfaults. Indeed, EigenSolver::eigenvectors returns a temporary MatrixXcd that is stored by reference into the CwiseUnaryView expression (.real()). Therefore, the variable ex is invalid right after its definition line. If you really want to waste time with the auto keyword then do:
or
But honestly, with Eigen it is really not recommended to use the auto keyword unless you really know what you are doing. So the best is really to do the following:
|
Registered Member
|
huh, good point and thanks for the clarification. I agree with you that it is generally a bad idea to mix auto with expression template.
|
Registered users: Bing [Bot], Google [Bot], Sogou [Bot]