Search code examples
eigenrcpp

Mapping Rcpp NumericVector to *static* or *fixed-size* Eigen Vectors?


This thread provides an example of converting an Rcpp::NumericVector to an Eigen::VectorXd:

Rcpp::cppFunction("bool conv(NumericVector X) { \
      Eigen::Map<Eigen::VectorXd> \
      XS(Rcpp::as<Eigen::Map<Eigen::VectorXd> >(X)); return true; } ", 
            depends="RcppEigen")
conv(1:4)

but I can't manage to adapt this to creating statically-sized or fixed-size Eigen containers

Rcpp::cppFunction("bool conv(NumericVector X) { \
      Eigen::Map<Eigen::Matrix<double,4,1>> \
      XS(Rcpp::as<Eigen::Map<Eigen::Matrix<double,4,1>> >(X)); return true; } ", 
                  depends="RcppEigen")
conv(1:4)

How can this be done?


Solution

  • Here is a minimal brute-force approach of instantiating a fixed-size 4x1 matrix ... and then using memcpy() to copy the payload over. As my comment earlier mentioned we have no code in RcppEigen that transfer from a SEXP R object to such an Eigen type so there is not a lot more we can do.

    Code

    #include <RcppEigen.h>
    
    // [[Rcpp::depends(RcppEigen)]]
    
    // [[Rcpp::export]]
    bool conv1(Rcpp::NumericVector X) {
        Eigen::Map<Eigen::VectorXd> XS(Rcpp::as<Eigen::Map<Eigen::VectorXd>>(X));
        return true;
    }
    
    // [[Rcpp::export]]
    bool conv2(Rcpp::NumericVector X) {
        const int n = 4;
        if (X.size() != n) Rcpp::stop("Wrong size");
        Eigen::Matrix<double,4,1> m;
        std::memcpy(&m[0,0], &X[0], n*sizeof(double));
        Rcpp::Rcout << m << std::endl;
        return true;
    }
    
    /*** R
    x <- as.numeric(1:4)
    conv1(x)
    conv2(x)
    */
    

    Output

    > Rcpp::sourceCpp("~/git/stackoverflow/76706728/answer.cpp")
    
    > x <- as.numeric(1:4)
    
    > conv1(x)
    [1] TRUE
    
    > conv2(x)
    1
    2
    3
    4
    [1] TRUE
    >