I've got some R code, that is somewhat slow, so I've been trying to write some c++ code directly in the R code using the 'inline' library.
This works well, and I'm now trying to tweak it.
I've only been able to make it work if I allocate the 'results' data structures in R and pass these as function parameters to the c function. I'm wondering if it is possible to have a non void c/c++ function in the R code, such that memory is allocated and returned from c/c++ and not R.
See example below:
library(inline)
cppSig <- signature(res="numeric",ary="numeric",len="integer")
cppBody <- "
int lens=len[0];
res[0]=0;
for(int j=0;j<lens;j++)
res[0] += ary[j];
res[0] /= (double) lens;
#if 0 //Is something like this possible?
double *rary = new double[lens];
for(int i=0;i<lens;i++) rary[i] = ary[i]-res[0];
return rary;
#endif
"
cfun <- cfunction( sig=list(myMean=cppSig),
body=list(cppBody),verbose=T,
convention=".C", cxxargs="-O3", cppargs="-O3",language="C++")
cfunWrap <- function(x)
cfun$myMean(res=0,ary=x,length(x))$res
cfunWrap(x=rnorm(100))
Thanks
There are a few things I'd do differently, particularly after even just a casual glance at the Rcpp documentation. So here is just a quick list:
wrap()
for these non-vector types; vectors of double are returned automatically. But you never ever use new
/delete
on them. See Writing R Extensions
for why..C()
call convention from the cfunction()
. Always use cxxfunction()
, or at least enable .Call()
. I am not sure how you missed that.cxxfunction()
. Look around for example for sourceCpp()
or cppFunction()
, or even read the vignette.Edit: Okay, here is a full example following the structure of your function (but we can do better, see below for that):
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector monkey(NumericVector ary) {
int lens = ary.length(); // objects can tell you about their length
double res=0;
for(int j=0;j<lens;j++) res += ary[j];
res /= (double) lens;
NumericVector rary(lens);
for(int i=0;i<lens;i++) rary[i] = ary[i]-res;
return rary;
}
// and we even include some R code to test automagically
/*** R
set.seed(42)
x <- rnorm(5) # just five to keep printout short
monkey(x)
cat("Check:")
x - mean(x)
*/
which, if you call it, also runs the R code at the bottom:
R> Rcpp::sourceCpp('/tmp/monkey.cpp')
R> set.seed(42)
R> x <- rnorm(5) # just five to keep printout short
R> monkey(x)
[1] 0.9296545 -1.0060021 -0.0781755 0.1915587 -0.0370356
R> cat("Check:")
Check:
R> x - mean(x)
[1] 0.9296545 -1.0060021 -0.0781755 0.1915587 -0.0370356
R>
But one of the key features of Rcpp is that you can even do the vector operation in C++:
R> cppFunction('NumericVector monkey2(NumericVector x) { return x - mean(x); }')
R> monkey2(x)
[1] 0.9296545 -1.0060021 -0.0781755 0.1915587 -0.0370356
R>
That just compiled a new one-line C++ function which operated on the whole vector x
and ran it.