Reversing a Vector

Dirk Eddelbuettel — written Dec 19, 2012 — source

To start with and for purposes of comparison, we reverse a numeric vector using the R C API (note that this example was taken from Jeff Ryan’s esotericR package):

#include <Rcpp.h>
using namespace Rcpp;

SEXP rev (SEXP x) {
  SEXP res;
  int i, r, P=0;
  PROTECT(res = Rf_allocVector(REALSXP, Rf_length(x))); P++;
  for(i=::Rf_length(x), r=0; i>0; i--, r++) {
     REAL(res)[r] = REAL(x)[i-1];
  }
  ::Rf_copyMostAttrib(x, res);
  UNPROTECT(P);
  return res;
}

Here’s the same operation implemented using Rcpp and calling the std::reverse function from the C++ standard library:

// [[Rcpp::export]]
NumericVector rcppRev(NumericVector x) {
   NumericVector revX = clone<NumericVector>(x);
   std::reverse(revX.begin(), revX.end());
   ::Rf_copyMostAttrib(x, revX); 
   return revX;
} 

Here’s an illustration of calling our rcppRev function from R:

obj <- structure(seq(0, 1, 0.1), obligatory="hello, world!")
obj
 [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
attr(,"obligatory")
[1] "hello, world!"
rcppRev(obj)
 [1] 1.0 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0.0
attr(,"obligatory")
[1] "hello, world!"

Both the obj variable and the new copy contain the desired data attribute, the new copy is reversed, the original is untouched. All in four lines of C++ not requiring explicit memory managment or easy to get wrong array manipulations.

tags: stl 

Related Articles