Yes, I can understand why it's not clear what the Cm_class is for (I did take out all the linear algebra and other parts of the class). That is, after all, a consequence of creating a minimal example. And, I am also happy to declare functions as you do. The point is, though, that the typedef used in the function definition does not work with the constructor for the Cm_class, even though they are conceptually the same thing. I appreciate your interest in what the purpose of the code is, but it's probably not worth trying to explain the reasons for why it's designed they way it is. I can already work around the problem, for instance by using two different typedefs and making sure they mesh properly at the right points (though it's annoying to have two different typedefs for a single conceptual thing), or other things I mentioned previously. The fundamental problem is, as you said, that RcppEigen doesn't know how to form an Eigen::Map<const Eigen::MatrixXd> with the as function. Unfortunately, this is the only way of creating a read-only mapping from a constant pointer (i.e. const double*) in Eigen (see below code). So, when 'as' operates I need to use a const Map<MatrixXd>, but when I want to create my own read-only mapping from a constant pointer I need a Map< const MatrixXd>, hence two different typedefs even though they're really supposed to be the same thing. In Eigen this works: const double *p=&somearray; Map<const MatrixXd> mapping(p, n, n); In Eigen this doesn't work: (maybe there's an argument to make Eigen allow this) const double *p=&somearray; const Map<MatrixXd> mapping(p, n, n);
On Thu, Jan 31, 2013 at 2:38 PM, Douglas Bates <bates at stat.wisc.edu> wrote:
Sorry but I am still struggling (even after reformatting the source code) to
understand what the problem is. For one thing it is not clear to me what
the Cm_class is for.
The fundamental rule for me is that I always declare functions like
//[[Rcpp::Export]]
Eigen::VectorXd testfunc(const MapVecd ytrait, const MapMatd xmat) {
...
}
If you need to get a pointer to the contents of the matrix you could use a
const_cast but in that case I don't understand why you would use the Eigen
classes. If all you want is the dimensions and a pointer to the contents
you should use NumericMatrix class.
On Thu, Jan 31, 2013 at 1:27 PM, M A <markoilcan at gmail.com> wrote:
Right. The problem comes up because of the constructor with one of my
classes. Here is a slightly extended minimal example:
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
#include <Rcpp.h>
typedef Eigen::Map<Eigen::VectorXd> MapVecd;
typedef Eigen::Map<Eigen::MatrixXd> MapMatd; // (A). This one works
with (1) below
//typedef Eigen::Map<const Eigen::MatrixXd> MapMatd; // (B). This one
fails with (1) below
class Cm_class {
public:
const MapMatd c_matrix;
//Cm_class( double *p_pdmat, const int nr, const int nc ) : //
Works with (A) or (B)
Cm_class( const double *p_pdmat, const int nr, const int nc ) : //
Works with (B) fails with (A)
c_matrix(p_pdmat, nr, nc) {}
};
//Eigen::VectorXd testfunc(const MapVecd ytrait, MapMatd xmat) { //
(1). This only works with (A)
// [[Rcpp::export]]
Eigen::VectorXd testfunc(const MapVecd ytrait) {
return ytrait;
}
I really want testfunc to be as in (1) where xmat gets mapped into a
double matrix, though I take it out above for simplicity. I have my
class constructor taking a const double*, but that fails with the
typedef (A), the way you recommend. To get that constructor
initialization to work I have to use typedef (B), but that causes
failure with (1), which is what I was originally writing about. I can
certainly work around this by removing the const from the double* in
the class constructor, etc, but I guess there's the larger question of
whether the RcppEigen 'as' function should be able to form an
Eigen::Map<const Eigen::MatrixXd>. Thanks for the info regarding the
point of failure.
Mark A
On Thu, Jan 31, 2013 at 11:34 AM, Douglas Bates <bates at stat.wisc.edu>
wrote:
I should check the syntax before sending the message. On Thu, Jan 31, 2013 at 11:30 AM, Douglas Bates <bates at stat.wisc.edu> wrote:
The as function in RcppEigen can form an Eigen::Map<Eigen::MatrixXd> but doesn't know how to form an Eigen::Map<const Eigen::MatrixXd> Generally I find that I confuse myself less when the const is outside the Eigen::Map. In other words, I use something like typedef Eigen::Map<Eigen::MatrixXd> mMat; const mMat M(mat_from_R);
That should be const mMat M = as<mMat>(mat_from_R); Well, at least I think so. The bottom line is that I find it easier to use const in the declaration of an instance of a class, not in the typedef.
This tells me that M is a mapped MatrixXd object which is constructed from the SEXP mat_from_R and is read-only. On Thu, Jan 31, 2013 at 11:01 AM, M A <markoilcan at gmail.com> wrote:
I am compiling some source code using sourceCpp and getting a
compiling failure when the source has the line with the const keyword
but no failure when it does not, in the below source.
// file: minimaltest.cpp
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
#include <Rcpp.h>
typedef Eigen::Map<Eigen::VectorXd> MapVecd;
//typedef Eigen::Map<Eigen::MatrixXd> MapMatd; // This one works
typedef Eigen::Map<const Eigen::MatrixXd> MapMatd; // This one fails
// [[Rcpp::export]]
Eigen::VectorXd testfunc(const MapVecd ytrait, MapMatd xmat) {
return ytrait;
}
This is the error:
sourceCpp("minimaltest.cpp")
g++ -arch x86_64 -I/Library/Frameworks/R.framework/Resources/include
-I/Library/Frameworks/R.framework/Resources/include/x86_64 -DNDEBUG
-I/usr/local/include
-I"/Library/Frameworks/R.framework/Versions/2.15/Resources/library/Rcpp/include"
-I"/Library/Frameworks/R.framework/Versions/2.15/Resources/library/RcppEigen/include"
-fPIC -g -O2 -c minimaltest.cpp -o minimaltest.o
Error in sourceCpp("minimaltest.cpp") :
Error 1 occurred building shared library.
/Library/Frameworks/R.framework/Versions/2.15/Resources/library/Rcpp/include/Rcpp/internal/Exporter.h:
In constructor ?Rcpp::traits::Exporter<T>::Exporter(SEXPREC*) [with T
= Eigen::Map<const Eigen::Matrix<double, -0x00000000000000001,
-0x00000000000000001, 0, -0x00000000000000001, -0x00000000000000001>,
0, Eigen::Stride<0, 0> >]?:
/Library/Frameworks/R.framework/Versions/2.15/Resources/library/Rcpp/include/Rcpp/as.h:67:
instantiated from ?T Rcpp::internal::as(SEXPREC*,
Rcpp::traits::r_type_generic_tag) [with T = Eigen::Map<const
Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001, 0,
-0x00000000000000001, -0x00000000000000001>, 0, Eigen::Stride<0, 0>
]?
/Library/Frameworks/R.framework/Versions/2.15/Resources/library/Rcpp/include/Rcpp/as.h:112: instantiated from ?T Rcpp::as(SEXPREC*) [with T = Eigen::Map<const Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001, 0, -0x00000000000000001, -0x00000000000000001>, 0, Eigen::Stride<0, 0>
]?
minimaltest.cpp:35: instantiated from here /Library/Frameworks/R.framework/Versions/2.15/Resources/library/Rcpp/include/Rcpp/internal/Exporter.h:31: error: no matching function for call to ?Eigen::Map<const Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001, 0, -0x00000000000000001, -0x00000000000000001>, 0, Eigen::Stride<0, 0>
::Map(SEXPREC*&)?
/Library/Frameworks/R.framework/Versions/2.15/Resources/library/RcppEigen/include/Eigen/src/Core/Map.h:164: note: candidates are: Eigen::Map<MatrixType, MapOptions, StrideType>::Map(typename Eigen::MapBase<Eigen::Map<PlainObjectType, MapOptions, StrideType>, (Eigen::internal::accessors_level<Eigen::Map<PlainObjectType, MapOptions, StrideType> >::has_write_access ? WriteAccessors : ReadOnlyAccessors)>::PointerType, typename Eigen::internal::traits<Eigen::Map<PlainObjectType, MapOptions, StrideType> >::Index, typename Eigen::internal::traits<Eigen::Map<PlainObjectType, MapOptions, StrideType> >::Index, const StrideType&) [with PlainObjectType = const Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001, 0, -0x00000000000000001, -0x00000000000000001>, int MapOptions = 0, StrideType = Eigen::Stride<0, 0>] /Library/Frameworks/R.framework/Versions/2.15/Resources/library/RcppEigen/include/Eigen/src/Core/Map.h:151: note: Eigen::Map<MatrixType, MapOptions, StrideType>::Map(typename Eigen::MapBase<Eigen::Map<PlainObjectType, MapOptions, StrideType>, (Eigen::internal::accessors_level<Eigen::Map<PlainObjectType, MapOptions, StrideType> >::has_write_access ? WriteAccessors : ReadOnlyAccessors)>::PointerType, typename Eigen::internal::traits<Eigen::Map<PlainObjectType, MapOptions, StrideType> >::Index, const StrideType&) [with PlainObjectType = const Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001, 0, -0x00000000000000001, -0x00000000000000001>, int MapOptions = 0, StrideType = Eigen::Stride<0, 0>] /Library/Frameworks/R.framework/Versions/2.15/Resources/library/RcppEigen/include/Eigen/src/Core/Map.h:139: note: Eigen::Map<MatrixType, MapOptions, StrideType>::Map(typename Eigen::MapBase<Eigen::Map<PlainObjectType, MapOptions, StrideType>, (Eigen::internal::accessors_level<Eigen::Map<PlainObjectType, MapOptions, StrideType> >::has_write_access ? WriteAccessors : ReadOnlyAccessors)>::PointerType, const StrideType&) [with PlainObjectType = const Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001, 0, -0x00000000000000001, -0x00000000000000001>, int MapOptions = 0, StrideType = Eigen::Stride<0, 0>] /Library/Frameworks/R.framework/Versions/2.15/Resources/library/RcppEigen/include/Eigen/src/Core/Map.h:106: note: Eigen::Map<const Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001, 0, -0x00000000000000001, -0x00000000000000001>, 0, Eigen::Stride<0, 0> >::Map(const Eigen::Map<const Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001, 0, -0x00000000000000001, -0x00000000000000001>, 0, Eigen::Stride<0, 0> >&) make: *** [minimaltest.o] Error 1 Here is my session info:
sessionInfo()
R version 2.15.2 (2012-10-26) Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit) locale: [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] RcppEigen_0.3.1.2 Matrix_1.0-9 lattice_0.20-10 Rcpp_0.10.2 loaded via a namespace (and not attached): [1] grid_2.15.2 tools_2.15.2 Note that the g++... portion works fine on the command line, so I guess the failure is somewhere in the building of the library. Of course I can get around this by not using the const keyword, but why is there a problem and what is the right fix? Thanks, Mark A
_______________________________________________ Rcpp-devel mailing list Rcpp-devel at lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel