Best idiom for populating a C ++ array from NumericVector

I use Rcpp to wrap a written algorithm (not by me) in C-like C ++ (without STL, without boost, I can’t do anything, as far as I can tell). You can see the implemented algorithm here (I wrap kmeans_w_03 ). Therefore, I pass the numeric vector from R, which then needs to be converted to a double array.

I am currently looping element by element and filling out one of the "tother", for example:

 SEXP testfn(SEXP weightvec, SEXP cluster_num_k){ Rcpp::NumericVector weightR(weightvec) ; int point_num = weightR.size(); double weight[point_num] ; for(int i = 0; i < point_num; ++i) { weight[i] = weightR[i]; } } 

But with singleton numerical vectors, I can take advantage of the superior customization functionality as Rcpp:

 int cluster_num = Rcpp::as<int>(cluster_num_k); 

Trying something similar for lengths> 1 of numerical vectors, however, results in a crash or error depending on the exact syntax variant:

 double weight[point_num] = Rcpp::as<double>(weightvec); 

I'm not necessarily against the loop, but I'm a complete neophyte and suspect the best way. I read the Rcpp introduction, the wiki tutorial on wiki and RcppExamples, and have not yet found anything to resolve this issue, but that does not mean that I did not just skip it. My reading of the Docsgen Rcpp docs is that as can use the STL vector but not an array (but it is very difficult for me to read these documents, so I suspect I'm wrong there). If so, I think I could pass the vector from there to the array too ....

So my question is: is there a better (less lines of code, more expressive code, and perhaps even able to avoid memory usage) way to convert NumericVector to double[] ?

+8
c ++ r rcpp
source share
3 answers

Ari, in the previous answer, John makes a good point. To expand a bit, there are several problems.

  • you are dealing with a library with an outdated coding standard that wants double[] or *double
  • You want to use the best coding standards and use Rcpp .

Well, be afraid, we have a simple solution. Activate Rcpp::NumericVector X(weightvec); as usual, then pass it to foo() (or something else) as

 foo(X.begin()) 

which gives you the required double* , and if necessary X.size() provides the length. Since you came from R, you do not need to worry about the scale and lifetime when you return to R after that.

If you need to be more explicit, I also used the uglier &(X[0]) .

In addition, the Rcpp::as<>() caster also works on std::vector<double> , so you can do

 std::vector<double> x = Rcpp::as<std::vector<double> >(weightvec); 

but besides converting to C ++ types, it gets nothing.

Finally, if Josh or other C-stamps are nearby, it all takes advantage of the fact that SEXP from R is guaranteed to have a continuous pointer C, so you can also go through the old REAL(weightvec) school.

+7
source share

Writing a C ++ program that does not use the standard library (what you call "STL") is not what I consider to be "normal C ++". The standard library is part of the language defined by the Standard. Thus, the use of tools defined in the standard is not unconventional C ++. On the contrary, I would suggest that knowingly ignoring these objects is itself unconventional. It uses C ++ as "better than C" or "C with classes." and that point is missing.

Keeping this in mind, looking at the fact that your loop intends to complete my first slope, you should use transform to copy the source to the destination and vector as the destination.

You also have an intermediary working here - first (apparently) copy the weightVec to the newly built NumericVector and then copy the elements from this - but the NumericVector will be thrown away, It seems wasteful to me.

Here is the basic pattern that I would have in mind when writing this code:

 vector<double> weight; transform( weightVec.begin(), weightVec.end(), back_inserter(weight), converter() ); return weight; 

There are some syntax bits that I cannot fill out without knowing more about the players in the game. But given what you do, the philosophy seems sound.

For example, a SEXP object may not have begin() or end() methods. However, you are already creating the NumericVector from the SEXP object directly, so SEXP probably has analog capabilities for begin() and end() , which you can use or even use directly.

The converter() construct that I use above is a placeholder for a function, functor, or lambda (in C ++ 11) that converts one SEXP element to double . Again, I do not know the details that I need to implement this, but it should be possible, since you are already doing it differently.

+4
source share

If your question is how COPY data from Rcpp::NumericVector to a C ++ array, transform() is a good answer. But if you want to get an internal array from Rcpp::NumericVector , which does not include any copying, you can do the same thing as extracting the array from std::vector :

 double* arr = &vec[0]; 

where vec is Rcpp::NumericVector .

0
source share

All Articles