I'm trying to write a function which can take in functions as its arguments in Rcpp. I have written an example function in R that shows the kind of functionality that I'm aiming for:
simulate_and_evaluate <- function(simulate, evaluate) {
y <- simulate(1)
eval <- evaluate(y)
return(eval)
}
simulate_fun <- function(n) rnorm(n, 0, 1)
evaluate_fun <- function(x) dnorm(x, 0, 1)
simulate_and_evaluate(simulate = simulate_fun,
evaluate = evaluate_fun)
In this function simulate_and_evaluate, this takes in two arguments which are both functions, one that simulates a number and one that evaluates a function with this simualted number. So as an example, we can simulate a value from a standard normal and evaluate the density of a standard normal at that point. Does anyone know if there's a way to do this in Rcpp?
Rcpp aims for seamless interfacing of R and C++ objects. As functions are first class R objects represented internally as a type a SEXP can take, we can of course also ship them with Rcpp. There are numerous examples.
So here we simply rewrite your function as a C++ function:
Rcpp::cppFunction("double simAndEval(Function sim, Function eval) {
double y = as<double>(sim(1));
double ev = as<double>(eval(y));
return(ev);
}")
And we can then set the RNG to the same value, run your R function and this C++ function and get the same value. Which is awesome.
R> set.seed(123)
R> simulate_and_evaluate(simulate = simulate_fun,
+ evaluate = evaluate_fun)
[1] 0.341
R> set.seed(123) # reset RNG
R> simAndEval(simulate_fun, evaluate_fun)
[1] 0.341
R>
But as #MrFlick warned you, this will not run any faster because we added no compiled execution of the actual functions we are merely calling them from C++ rathern than R.
The topic has been discussed before. Please search StackOverflow, maybe with a string [rcpp] Function to get some meaningful hits.
Related
I'm trying to get a vector of polynomials, but within the vector have each polynomial defined by a function in Pari.
For example, I want to be able to output a vector of this form:
[f(x) = x-1 , f(x) = x^2 - 1, f(x) = x^3 - 1, f(x) = x^4 - 1, f(x) = x^5 - 1]
A simple vector construction of vector( 5, n, f(x) = x^n-1) doesn't work, outputting [(x)->my(i=1);x^i-1, (x)->my(i=2);x^i-1, (x)->my(i=3);x^i-1, (x)->my(i=4);x^i-1, (x)->my(i=5);x^i-1].
Is there a way of doing this quite neatly?
Update:
I have a function which takes a polynomial in two variables (say x and y), replaces one of those variables (say y) with exp(I*t), and then integrates this between t=0 and t=1, giving a single variable polynomial in x: int(T)=intnum(t=0,1,T(x,exp(I*t)))
Because of the way this is defined, I have to explicitly define a polynomial T(x,y)=..., and then calculate int(T). Simply putting in a polynomial, say int(x*y)-1, returns:
*** at top-level: int(x*y-1)
*** ^----------
*** in function int: intnum(t=0,1,T(x,exp(I*t)))
*** ^--------------
*** not a function in function call
*** Break loop: type 'break' to go back to GP prompt
I want to be able to do this for many polynomials, without having to manually type T(x,y)=... for every single one. My plan is to try and do this using the apply feature (so, putting all the polynomials in a vector - for a simple example, vector(5, n, x^n*y-1)). However, because of the way I've defined int, I would need to have each entry in the vector defined as T(x,y)=..., which is where my original question spawned from.
Defining T(x,y)=vector(5, n, x^n*y-1) doesn't seem to help with what I want to calculate. And because of how int is defined, I can't think of any other way to go about trying to tackle this.
Any ideas?
The PARI inbuilt intnum function takes as its third argument an expression rather than a function. This expression can make use of the variable t. (Several inbuilt functions behave like this - they are not real functions).
Your int function can be defined as follows:
int(p)=intnum(t=0, 1, subst(p, y, exp(I*t)))
It takes as an argument a polynomial p and then it substitutes for y when required to do so.
You can then use int(x*y) which returns (0.84147098480789650665250232163029899962 + 0.45969769413186028259906339255702339627*I)*x'.
Similarly you can use apply with a vector of polynomials. For example:
apply(int, vector(5, n, x^n*y-1))
Coming back to your original proposal - it's not technically wrong and will work. I just wouldn't recommend it over the subst method, but perhaps if you are were wanting to perform numerical integration over a class of functions that were not representable as polynomials. Let's suppose int is defined as:
int(T)=intnum(t=0,1,T(x,exp(I*t)))
You can invoke it using the syntax int((x,y) -> x*y). The arrow is the PARI syntax for creating an anonymous function. (This is the difference between an expression and a function - you cannot create your own functions that work like PARI inbuilt functions)
You may even use it with a vector of functions:
apply(int, vector(5, n, (x,y)->x^n*y-1))
I am using the syntax (x,y)->x^n*y-1 here which is preferable to the f(x,y)=x^n*y-1 you had in your question, but they are essentially the same. (the latter form also defines f as a side effect which is not wanted so it is better to use anonymous functions.
I have just spent a while trying to find a bug in my code which has turned out to be an unusual (at least to me) parameterisation for the R::dexp function. For example:
cppFunction("
double my_dexp(double x, double lambda, double is_log) {
return R::dexp(x, lambda, is_log);
}
")
> my_dexp(4.5, 2.5, FALSE)
[1] 0.06611956
> dexp(4.5, 2.5, FALSE)
[1] 3.251824e-05
Looking here I can see that they use the definition:
double R::dexp(double x, double sl, int lg)
but I haven't been able to find out what sl stands for. I'm not sure if this is documented anywhere - so hopefully this post stands as a warning to others who have used the function like me, and also if anyone can help as to what parameterisation has been used, and why.
If you look at the function definition for dexp,
R> dexp
function (x, rate = 1, log = FALSE)
.Call(C_dexp, x, 1/rate, log)
you'll see that dexp calls the C function C_dexp with parameter 1/rate. This is what R::dexp is mirroring. In Rcp, they always use the same parameterisation as R itself does at the C level which may be different than the R level.
That means
R> my_dexp(4.5, 1/2.5, FALSE) - dexp(4.5, 2.5, FALSE)
[1] 0
If you look at the Wikipedia page on the exponential function, you'll see the alternative parameterisation based on the reciprocal of the rate parameter, lambda. In this parameterisation, the parameter beta=1/lambda takes the role of a survival parameter. So the expected duration of survival of the system is beta units of time.
R uses, when interfacing with other languages, the header R_ext/Complex.h which includes the type Rcomplex which seems to be an implementation of std::complex<double>. The standard way of using it would be for a complex vector x_ in R:
Rcomplex *px = COMPLEX(x_);
However, since I need to pass it to armadillo I then do:
arma::cx_vec x(px, nrows(x_), false, false);
but armadillo does not accept Rcomplex types. I have tried doing instead:
std::complex<double> *px = COMPLEX(x_);
but get the following error: cannot convert ‘Rcomplex*’ to ‘std::complex<double>*’ in initialization
Do you have any clue for passing a complex vector in R to std::complex<double> type? I am aware of Rcpp but would like to have a direct solution relying on base R.
EDIT: Following one of the comments, I wanted to clarify that Rcomplex is of C type but that it is compatible with std::complex<double> according to the answer by #Stephen Canon.
EDIT2: Why does Dirk's answer have more votes than the accepted answer if it is not answering the "without dependencies" question. In addition, I have been downvoted apparently because if one wants preferably to use base R with C or C++ somebody does not like it. Anyway, I have better things to do but this is not the first time that I get no answer to my original question when asking something related to base R interfacing with C or C++ and get a Rcpp related answer that I have not asked for.
Complex numbers are less common in statistics so that has not been an initial focus. However there are use cases Baptiste has one or two packages which pushes to add features to the interface given the existing support in Armadillo and R.
So all the work is done for you in templates -- here is the simplest possibly example of passing complex-values matrix and returning its sum:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::cx_mat foo(const arma::cx_mat & C) {
return C + C;
}
/*** R
C <- matrix( (1+1i) * 1:4, 2, 2)
C
foo(C)
*/
It does what you'd expect:
R> sourceCpp("/tmp/armaComplex.cpp")
R> C <- matrix( (1+1i) * 1:4, 2, 2)
R> C
[,1] [,2]
[1,] 1+1i 3+3i
[2,] 2+2i 4+4i
R> foo(C)
[,1] [,2]
[1,] 2+2i 6+6i
[2,] 4+4i 8+8i
R>
So we start with complex values in R, pass them via Rcpp and RcppArmadillo to Armadillo and get them back to R. Without writing an additional line of code, and no discernible overhead.
One type can always be forced to another type using reinterpret_cast. Generally this is a bad idea, but if you can guarantee that the two complex types are indeed compatible, you can do:
Rcomplex* px = COMPLEX(x_);
arma::cx_vec x( reinterpret_cast<arma::cx_double*>(px), nrows(x_), false, false );
The type arma::cx_double is a shorthand for std::complex<double>
I mainly use R, but eventually would like to use Rcpp to interface with some C++ functions that take in and return 2d numeric arrays. So to start out playing around with C++ and Rcpp, I thought I'd just make a little function that converts my R list of variable-length numeric vectors to the C++ equivalent and back again.
require(inline)
require(Rcpp)
test1 = cxxfunction(signature(x='List'), body =
'
using namespace std;
List xlist(x);
int xlen = xlist.size();
vector< vector<int> > xx;
for(int i=0; i<xlen; i++) {
vector<int> test = as<vector<int> > (xlist[i]);
xx.push_back(test);
}
return(wrap(xx));
'
, plugin='Rcpp')
This works like I expect:
> test1(list(1:2, 4:6))
[[1]]
[1] 1 2
[[2]]
[1] 4 5 6
Admittedly I am only part way through the very thorough documentation, but is there a nicer (i.e. more Rcpp-like) way to do the R -> C++ conversion than with the for loop? I am thinking possibly not, since the documentation mentions that (at least with the built-in methods) as "offers less flexibility and currently handles conversion of R objects into primitive types", but I wanted to check because I'm very much a novice in this area.
I will give you bonus points for a reproducible example, and of course for using Rcpp :) And then I will take those away for not asking on the rcpp-devel list...
As for converting STL types: you don't have to, but when you decide to do it, the as<>() idiom is correct. The only 'better way' I can think of is to do name lookup as you would in R itself:
require(inline)
require(Rcpp)
set.seed(42)
xl <- list(U=runif(4), N=rnorm(4), T2df=rt(4,2))
fun <- cxxfunction(signature(x="list"), plugin="Rcpp", body = '
Rcpp::List xl(x);
std::vector<double> u = Rcpp::as<std::vector<double> >(xl["U"]);
std::vector<double> n = Rcpp::as<std::vector<double> >(xl["N"]);
std::vector<double> t2 = Rcpp::as<std::vector<double> >(xl["T2df"]);
// do something clever here
return(R_NilValue);
')
Hope that helps. Otherwise, the list is always open...
PS As for the two-dim array, that is trickier as there is no native C++ two-dim array. If you actually want to do linear algebra, look at RcppArmadillo and RcppEigen.
Since last night I have been trying out Rcpp and inline, and so far I am really enjoying it. But I am kinda new to C in general and can only do basic stuff yet, and I am having a hard time finding help online on things like functions.
Something I was working on was a function that finds the minimum of a vector in the global environment. I came up with:
library("inline")
library("Rcpp")
foo <- rnorm(100)
bar <- cxxfunction( signature(),
'
Environment e = Environment::global_env();
NumericVector foo = e["foo"];
int min;
for (int i = 0; i < foo.size(); i++)
{
if ( foo[i] < foo[min] ) min = i;
}
return wrap(min+1);
', plugin = "Rcpp")
bar()
But it seems like there should be an easier way to do this, and it is quite slower than which.max()
system.time(replicate(100000,bar()))
user system elapsed
0.27 0.00 0.26
system.time(replicate(100000,which.min(foo)))
user system elapsed
0.2 0.0 0.2
Am I overlooking a basic c++ or Rcpp function that does this? And if so, where could I find a list of such functions?
I guess this question is related to:
Where can I learn how to write C code to speed up slow R functions?
but different in that I am not really interested in how to incorporate c++ in R, but more on how and where to learn basic c++ code that is usable in R.
Glad you are finding Rcpp useful.
The first comment by Billy is quite correct. There is overhead in the function lookup and there is overhead in the [] lookup for each element etc.
Also, a much more common approach is to take a vector you have in R, pass it to a compiled function you create via inline and Rcpp, and have it return the result. Try that. There are plenty of examples in the package and scattered over the rcpp-devel mailing list archives.
Edit: I could not resist trying to set up a very C++ / STL style answer.
R> src <- '
+ Rcpp::NumericVector x(xs);
+ Rcpp::NumericVector::iterator it = // iterator type
+ std::min_element(x.begin(), x.end()); // STL algo
+ return Rcpp::wrap(it - x.begin()); '
R> minfun <- cxxfunction(signature(xs="numeric"), body=src, plugin="Rcpp")
R> minfun(c(7:20, 3:5))
[1] 14
R>
That is not exactly the easiest answer but it shows how by using what C++ offers you can find a minimum element without an (explicit) loop even at the C++ level. But the builtin min() function is still faster.
*Edit 2: Corrected as per Romain's comment below.