简体   繁体   中英

Rcpp - transform NumericVector with binary function?

I'm looking at speeding up some R code by re-writing in C++ & integrating via Rcpp. My Cpp is, to say the least, rusty: so would appreciate any suggestions. In particular, I'm looking for pointers on mapping a function onto all elements of an Rcpp NumericVector . Here's an example.

I need to produce a new vector as follows:

  • Take a tail slice of an existing NumericVector ;
  • divide through each element of the new slice by a divisor

I have this so far:

// [[Rcpp::export]]
NumericVector cppAdjustProbabilities(  NumericVector& currentProbs, 
                                       const int index,
                                       const double divisor ) {

  //Note index <=0, e.g. -1 means remove first element
  if(index == 0) {
    return(currentProbs);
  } else {
    NumericVector newProbs = no_init(currentProbs.size()+index);                 
    NumericVector::iterator i = currentProbs.begin() - index; 
    NumericVector::iterator j = newProbs.begin();
    for(; i != currentProbs.end(); ++i, ++j) {
      *j=*i/divisor;
    }    
    return(newProbs);
  }
}

This works, but I'd prefer to use a "map" approach. I looked at std::transform , but it only supports a unary operation on vector elements - so I can't see how to pass the divisor in. This, for example, isn't valid:

std::transform(currentProbs.begin()-index, currentProbs.end(),
               newProbs.begin(), [](double val) { return (val / divisor);} );

Is there a way to bring the divisor into scope in the lambda? Or another way of doing it?

Thanks

With c++ lambda functions you can capture a value like this:

src1 <- 'NumericVector cppAdjustProbabilities(  NumericVector& currentProbs, 
                                       const int index,
                                       const double divisor ) {

  //Note index <=0, e.g. -1 means remove first element
  if(index == 0) {
    return(currentProbs);
  } else {
    NumericVector newProbs = no_init(currentProbs.size()+index);
    std::transform(currentProbs.begin()-index, currentProbs.end(),
               newProbs.begin(), [&divisor](double val) { return (val / divisor);} );
               //                 ^^^^^^^^
    return(newProbs);
  }
}'

Rcpp::cppFunction(src1)

currentProbs <- c(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)
index <- -5L
divisor <- 2.0
cppAdjustProbabilities(currentProbs, index, divisor)
#> [1] 0.30 0.35 0.40 0.45

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM