Statistically Irrelevant Home About
Simple Rcpp functions
17 May 2015
R is great for many things, but it can be sometimes it can be slow (e.g. for loops, or see this
post which benchmarks a few algorithms for several languages). In such cases, it would be
great to have the option to write a particular function in a compiled language, and then call it
from R.
Fortunately such an option exists, which is the Rcpp package. See this post by Hadley
Wickham, or this page by the maintainer Dirk Eddelbuettel for more information.
However, while there are a few sources for supporting material to explain how to use the
package, there seems to be a shortage of 'starter' examples, i.e. examples that one can start
with, and then modify for one's own purposes.
A simple Rcpp function
Below we rewrite the multiply.R function in C++ in the file multiplyCpp.cpp .
// multiplyCpp.cpp
#include<Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double multiplyCpp(double a, double b){
return (a*b);
}
The key line here is the // [[Rcpp::export]] , which allows R call the C++ function.
Then in R, in the same folder containing the multiplyCpp.cpp file, the following lines will call
the function multiplyCpp :
> Rcpp::sourceCpp("multiplyCpp.cpp")
> multiplyCpp(3, 4) # returns 12
> multiplyCpp(3.4, 4.3) # returns 14.62
Clearly, the key line in R is Rcpp::sourceCpp . As usual, it could have been written as two
separate lines:
> library(Rcpp)
> sourceCpp("multiplyCpp.cpp")
This is almost the simplest function. The next examples deal with passing vectors.
Evaluating vectors in Rcpp
Rcpp has a class called NumericVector which handles vectors of integers/doubles. A simple
function which calculates the sum of a vector is below:
// sumCpp.cpp
#include<Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double sumCpp(NumericVector x){
double sum = 0;
int n = x.size();
for (int i=0; i < n; i++){
sum += x[i];
}
return sum;
}
Below are some examples:
> Rcpp::sourceCpp("sumCpp.cpp")
> x <- c(4, 6, 7)
> sumCpp(x) # returns 17
> y <- c(8, 9.5, 7.62)
> sumCpp(y) # returns 25.12
Separating C++ and Rcpp code
It might be desirable to separate C++ code from Rcpp code, so that the C++ functions could be
reused in 'pure' C++ scripts - in other words, writing an Rcpp wrapper function. This is one way
to do it:
// sumCppWrapped.cpp
#include<Rcpp.h>
using namespace Rcpp;
//C++ code without Rcpp
double sumCppOnly(double* x, int n){
double sum = 0;
for (int i=0; i < n; i++){
sum += x[i];
}
return sum;
}
// Rcpp wrapper for C++ function
// [[Rcpp::export]]
double sumCppWrapped(NumericVector x){
return sumCppOnly(x.begin(), x.size());
}
Examples (in an R terminal):
> Rcpp::sourceCpp("sumCppWrapped.cpp")
> sumCppWrapped(c(5, 6)) # 11
> sumCppWrapped(c(1.12, 2.021)) # 3.141
Returning vectors in Rcpp
Processing and returning vectors using is easy using NumericVector . The function below
simply adds two to every element in the array.
// addTwo.cpp
#include<Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector addTwo(NumericVector x){
int n = x.size();
for (int i=0; i < n; i++){
x[i] += 2;
}
return x;
}
Quick examples (in an R terminal):
> Rcpp::sourceCpp("addTwo.cpp")
> x <- c(2, 3, 5)
> addTwo(x) # returns (4, 5, 7)
> y <- c(3, 9.5, 7.62)
> addTwo(y) # returns (5, 11.5, 9.62)
Unfortunately, making a wrapper function which casts a double* array back into a
NumericVector seems to be a bit tricky - once I figure out how to do it I'll update this post.