Reputation: 747
This is an Rcpp conversion related Q. I'm looking to convert a long std::vector into a Rcpp matrix object, but want to know if there is an easy conversion format. Naturally, you could loop over each element and fill an empty Rcpp matrix, but this seems error prone and possibly needless if a more convenient approach is possible.
The reason I'm asking is I would like to utilize OpenMP in some existing C++ code, but storing element in the Rcpp matrix object directly in an OpenMP loop doesn't appear to work well (whereas loading a std::vector object and converting to a matrix after the OpenMP loop is complete seems to be a decent approach to the problem).
Any help would be greatly appreciated!
Upvotes: 18
Views: 7566
Reputation: 21315
To expand on Dirk's answer; R matrices are really just vectors with a dim
attribute set
> x <- 1
> y <- as.matrix(x)
> .Internal( inspect(x) )
@7f81a6c80568 14 REALSXP g0c1 [MARK,NAM(2)] (len=1, tl=0) 1 ## data
> .Internal( inspect(y) )
@7f81a3ea86c8 14 REALSXP g0c1 [NAM(2),ATT] (len=1, tl=0) 1 ## data
ATTRIB:
@7f81a3e68e08 02 LISTSXP g0c0 []
TAG: @7f81a30013f8 01 SYMSXP g1c0 [MARK,LCK,gp=0x4000] "dim" (has value)
@7f81a3ea8668 13 INTSXP g0c1 [NAM(2)] (len=2, tl=0) 1,1
Notice how the 'data' component of x
and y
are just REALSXP
s, but you have this extra dim
component on the matrix. Using this, we can easily convert a NumericVector
to a matrix in Rcpp
.
(Note: in the example below, I use SEXP
in the attributes just so the conversions between types are explicit):
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
SEXP vec_to_mat(SEXP x_) {
std::vector<double> x = as< std::vector<double> >(x_);
/* ... do something with x ... */
NumericVector output = wrap(x);
output.attr("dim") = Dimension(x.size(), 1);
return output;
}
/*** R
m <- c(1, 2, 3)
vec_to_mat(m)
*/
gives me
> m <- c(1, 2, 3)
> vec_to_mat(m)
[,1]
[1,] 1
[2,] 2
[3,] 3
So, you can use the Dimension
class and assign it to the dim
attribute of a vector to make a matrix 'by hand' in Rcpp.
Upvotes: 23
Reputation: 368599
You chose a good approach. In the OpenMP context, you have to stay away from the single-threaded R. So std::vector
is good.
And yes, we have constructors from std::vector
to Rcpp::NumericVector
and Rcpp::NumericMatrix
(which is after all just a vector with a dimensions attribute) as well as the Rcoo:Integer*
variants, as well as the usual as<>
and wrap
converters.
There should be plenty of examples in the Rcpp unit tests, the Rcpp examples, and of course on the Rcpp Gallery site.
Edit: Here is an overly simple example:
R> cppFunction('NumericVector phil(int n) { std::vector<double> x(n);
+ return wrap(x); }')
R> phil(4)
[1] 0 0 0 0
R>
Upvotes: 16