I have an R code with a bunch of user-defined R functions. I'm trying to make the code run faster and of course the best option is to use Rcpp. My code involves functions that call each other. Therefore, If I write some functions in C++, I should be able to call and to run some of my R functions in my c++ code. In a simple example consider the code below in R:
mySum <- function(x, y){
return(2*x + 3*y)
}
x <<- 1
y <<- 1
Now consider the C++ code in which I'm trying to access the function above:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
int mySuminC(){
Environment myEnv = Environment::global_env();
Function mySum = myEnv["mySum"];
int x = myEnv["x"];
int y = myEnv["y"];
return wrap(mySum(Rcpp::Named("x", x), Rcpp::Named("y", y)));
}
When I source the file in R with the inline function sourceCpp(), I get the error:
"invalid conversion from 'SEXPREC*' to int
Could anyone help me on debugging the code? Is my code efficient? Can it be summarized? Is there any better idea to use mySum function than what I did in my code?
Thanks very much for your help.
You declare that the function should return an int, but use wrap which indicates the object returned should be a SEXP. Moreover, calling an R function from Rcpp (through Function) also returns a SEXP.
You want something like:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
SEXP mySuminC(){
Environment myEnv = Environment::global_env();
Function mySum = myEnv["mySum"];
int x = myEnv["x"];
int y = myEnv["y"];
return mySum(Rcpp::Named("x", x), Rcpp::Named("y", y));
}
(or, leave function return as int and use as<int> in place of wrap).
That said, this is kind of non-idiomatic Rcpp code. Remember that calling R functions from C++ is still going to be slow.
Related
I have a C function from a down-stream library that I call in C like this
result = cfunction(input_function)
input_function is a callback that needs to have the following structure
double input_function(const double &x)
{
return(x*x);
}
Where x*x is a user-defined computation that is usually much more complicated. I'd like to wrap cfunction using Rcpp so that the R user could call it on arbitrary R functions.
NumericVector rfunction(Function F){
NumericVector result(1);
// MAGIC THAT I DON'T KNOW HOW TO DO
// SOMEHOW TURN F INTO COMPATIBLE input_funcion
result[0] = cfunction(input_function);
return(result);
}
The R user then might do rfunction(function(x) {x*x}) and get the right result.
I am aware that calling R functions within cfunction will kill the speed but I figure that I can figure out how to pass compiled functions later on. I'd just like to get this part working.
The closest thing I can find that does what I need is this https://sites.google.com/site/andrassali/computing/user-supplied-functions-in-rcppgsl which wraps a function that uses callback that has an oh-so-useful second parameter within which I could stuff the R function.
Advice would be gratefully received.
One possible solution would be saving the R-function into a global variable and defining a function that uses that global variable. Example implementation where I use an anonymous namespace to make the variable known only within the compilation unit:
#include <Rcpp.h>
extern "C" {
double cfunction(double (*input_function)(const double&)) {
return input_function(42);
}
}
namespace {
std::unique_ptr<Rcpp::Function> func;
}
double input_function(const double &x) {
Rcpp::NumericVector result = (*func)(x);
return result(0);
}
// [[Rcpp::export]]
double rfunction(Rcpp::Function F){
func = std::make_unique<Rcpp::Function>(F);
return cfunction(input_function);
}
/*** R
rfunction(sqrt)
rfunction(log)
*/
Output:
> Rcpp::sourceCpp('57137507/code.cpp')
> rfunction(sqrt)
[1] 6.480741
> rfunction(log)
[1] 3.73767
I am considering calling a R function from c++ via environment, but I got an error, here is what I did
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector call(NumericVector x){
Environment env = Environment::global_env();
Function f = env["fivenum"];
NumericVector res = f(x);
return res;
}
Type call(x), this is what I got,
Error: cannot convert to function
I know I can do it right in another way,
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector callFunction(NumericVector x, Function f) {
NumericVector res = f(x);
return res;
}
and type
callFunction(x,fivenum)
But still wondering why first method failed.
fivenum function is not defined in the global environment but in the stats package enviroment, so you should get it from that:
...
Environment stats("package:stats");
Function f = stats["fivenum"];
...
In addition to #digEmAll's answer, I would like to mention a more general approach, which mimics R's packagename::packagefunctionX(...) approach.
The advantage is that you don't have to call library("dependend_library"), i.e., in this case, library(stats). That is useful when you call a function from your package, without previously calling library.
// [[Rcpp::export]]
Rcpp::NumericVector five_nums(Rcpp::NumericVector x){
Rcpp::Environment stats = Rcpp::Environment::namespace_env("stats");
Rcpp::Function f = stats["fivenum"];
return Rcpp::NumericVector(f(x));
}
/*** R
five_nums(stats::rnorm(25, 2, 3))
*/
I am translating my R code with some prepared functions to RcppArmadillo. I want to use some of these functions directly in my Rcpp code,instead of translating. For example, I want to call the sigma2 function:
sigma2<- function(xi.vec,w.vec,log10lambda,n,q){
lambda <- 10^log10lambda
(1/(n-q))*sum((lambda*xi.vec*(w.vec^2))/(lambda*xi.vec+1))
}
A typical Rcpp code is as below:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
SEXP myS(){
Rcpp::Environment myEnv = Rcpp::Environment::global_env();
Rcpp::Function myS = myEnv["sigma2"];
arma::vec xvec = myEnv["xi.vec"];
arma::vec wvec = myEnv["w.vec"];
double l = myEnv["log10lambda"];
int n = myEnv["n"];
int q = myEnv["q"];
return myS(Rcpp::Named("xi.vec",xvec),
Rcpp::Named("w.vec",wvec),
Rcpp::Named("l",l),
Rcpp::Named("n",n),
Rcpp::Named("q",q));
}
Of course it works. But my problem is that in my case, the parameters of sigma2 function should be defined before as output of another function(say func1) in RcppArmadillo and they have armadillo data type. For instance, xi.vec and w.vec have vec type. Now I want to know how can I modified this code to call sigma2? Do I need to change my environment?
First, just say no to embedding R functions and environments into C++ routines. There is no speedup in this case; only a considerable slowdown. Furthermore, there is a greater potential for things to go cockeye if the variables are not able to be retrieved in the global.env scope.
In your case, you seem to be calling myS() from within myS() with no terminating condition. Thus, your function will never end.
e.g.
SEXP myS(){
Rcpp::Function myS = myEnv["sigma2"];
return myS(Rcpp::Named("xi.vec",xvec),
Rcpp::Named("w.vec",wvec),
Rcpp::Named("l",l),
Rcpp::Named("n",n),
Rcpp::Named("q",q));
}
Switch one to be myS_R and myS_cpp.
Regarding environment hijacking, you would need to pass down to C++ the values. You cannot reach into an R function to obtain values specific passed to it before it is called.
e.g.
SEXP myS_cpp(arma::vec xvec, arma::vec wvec, double l, int n, int q){
// code here
}
This question already has answers here:
Call a function from c++ via environment Rcpp
(2 answers)
Closed 6 years ago.
I was trying to call the sd(x), which is a R function, in Rcpp. I've seen an example of calling the R function dbate(x) in Rcpp and it works perfectly.
// dens calls the pdf of beta distribution in R
//[[Rcpp::export]]
double dens(double x, double a, double b)
{
return R::dbeta(x,a,b,false);
}
But when I tired to apply this method to sd(x) as following, it went wrong.
// std calls the sd function in R
//[[Rcpp::export]]
double std(NumericVector x)
{
return R::sd(x);
}
Does anyone know why this doesn't work?
There are a few issues with your code.
std is related to the C++ Standard Library namespace
This is triggering:
error: redefinition of 'std' as different kind of symbol
The R:: is a namespace that deals with Rmath functions. Other R functions will not be found in within this scope.
To directly call an R function from within C++ you must use Rcpp::Environment and Rcpp::Function as given in the example sd_r_cpp_call().
There are many issues with this approach though including but not limited to the loss of speed.
It is ideal to use Rcpp sugar expressions or implement your own method.
With this being said, let's talk code:
#include <Rcpp.h>
//' #title Accessing R's sd function from Rcpp
// [[Rcpp::export]]
double sd_r_cpp_call(const Rcpp::NumericVector& x){
// Obtain environment containing function
Rcpp::Environment base("package:stats");
// Make function callable from C++
Rcpp::Function sd_r = base["sd"];
// Call the function and receive its list output
Rcpp::NumericVector res = sd_r(Rcpp::_["x"] = x,
Rcpp::_["na.rm"] = true); // example of additional param
// Return test object in list structure
return res[0];
}
// std calls the sd function in R
//[[Rcpp::export]]
double sd_sugar(const Rcpp::NumericVector& x){
return Rcpp::sd(x); // uses Rcpp sugar
}
/***R
x = 1:5
r = sd(x)
v1 = sd_r_cpp_call(x)
v2 = sd_sugar(x)
all.equal(r,v1)
all.equal(r,v2)
*/
I am considering calling a R function from c++ via environment, but I got an error, here is what I did
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector call(NumericVector x){
Environment env = Environment::global_env();
Function f = env["fivenum"];
NumericVector res = f(x);
return res;
}
Type call(x), this is what I got,
Error: cannot convert to function
I know I can do it right in another way,
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector callFunction(NumericVector x, Function f) {
NumericVector res = f(x);
return res;
}
and type
callFunction(x,fivenum)
But still wondering why first method failed.
fivenum function is not defined in the global environment but in the stats package enviroment, so you should get it from that:
...
Environment stats("package:stats");
Function f = stats["fivenum"];
...
In addition to #digEmAll's answer, I would like to mention a more general approach, which mimics R's packagename::packagefunctionX(...) approach.
The advantage is that you don't have to call library("dependend_library"), i.e., in this case, library(stats). That is useful when you call a function from your package, without previously calling library.
// [[Rcpp::export]]
Rcpp::NumericVector five_nums(Rcpp::NumericVector x){
Rcpp::Environment stats = Rcpp::Environment::namespace_env("stats");
Rcpp::Function f = stats["fivenum"];
return Rcpp::NumericVector(f(x));
}
/*** R
five_nums(stats::rnorm(25, 2, 3))
*/