177 lines
4.1 KiB
R
177 lines
4.1 KiB
R
|
|
||
|
suppressMessages(library(Rcpp))
|
||
|
suppressMessages(library(inline))
|
||
|
suppressMessages(library(rbenchmark))
|
||
|
|
||
|
## NOTE: Within this section, the new way to compile Rcpp code inline has been
|
||
|
## written. Please use the code next as a template for your own project, and
|
||
|
## do NOT use the old code below
|
||
|
|
||
|
cppFunction('
|
||
|
NumericVector rcppGamma(NumericVector x){
|
||
|
int n = x.size();
|
||
|
|
||
|
const double y = 1.234;
|
||
|
for (int i=0; i<n; i++) {
|
||
|
x[i] = R::rgamma(3.0, 1.0/(y*y+4));
|
||
|
}
|
||
|
|
||
|
// Return to R
|
||
|
return x;
|
||
|
}')
|
||
|
|
||
|
## This approach is a bit sloppy. Generally, you will want to use
|
||
|
## sourceCpp() if there are additional includes that are required.
|
||
|
cppFunction('
|
||
|
NumericVector gslGamma(NumericVector x){
|
||
|
int n = x.size();
|
||
|
|
||
|
gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);
|
||
|
const double y = 1.234;
|
||
|
for (int i=0; i<n; i++) {
|
||
|
x[i] = gsl_ran_gamma(r,3.0,1.0/(y*y+4));
|
||
|
}
|
||
|
gsl_rng_free(r);
|
||
|
|
||
|
// Return to R
|
||
|
return x;
|
||
|
}', includes = '#include <gsl/gsl_rng.h>
|
||
|
#include <gsl/gsl_randist.h>',
|
||
|
depends = "RcppGSL")
|
||
|
|
||
|
|
||
|
cppFunction('
|
||
|
NumericVector rcppNormal(NumericVector x){
|
||
|
int n = x.size();
|
||
|
|
||
|
const double y = 1.234;
|
||
|
for (int i=0; i<n; i++) {
|
||
|
x[i] = R::rnorm(1.0/(y+1),1.0/sqrt(2*y+2));
|
||
|
}
|
||
|
|
||
|
// Return to R
|
||
|
return x;
|
||
|
}')
|
||
|
|
||
|
|
||
|
## Here we demonstrate the use of sourceCpp() to show the continuity
|
||
|
## of the code artifact.
|
||
|
|
||
|
sourceCpp(code = '
|
||
|
#include <RcppGSL.h>
|
||
|
#include <gsl/gsl_rng.h>
|
||
|
#include <gsl/gsl_randist.h>
|
||
|
|
||
|
using namespace Rcpp;
|
||
|
|
||
|
// [[Rcpp::depends("RcppGSL")]]
|
||
|
|
||
|
// [[Rcpp::export]]
|
||
|
NumericVector gslNormal(NumericVector x){
|
||
|
int n = x.size();
|
||
|
|
||
|
gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);
|
||
|
const double y = 1.234;
|
||
|
for (int i=0; i<n; i++) {
|
||
|
x[i] = 1.0/(y+1)+gsl_ran_gaussian(r,1.0/sqrt(2*y+2));
|
||
|
}
|
||
|
gsl_rng_free(r);
|
||
|
|
||
|
// Return to R
|
||
|
return x;
|
||
|
}')
|
||
|
|
||
|
x <- rep(NA, 1e6)
|
||
|
res <- benchmark(rcppGamma(x),
|
||
|
gslGamma(x),
|
||
|
rcppNormal(x),
|
||
|
gslNormal(x),
|
||
|
columns=c("test", "replications", "elapsed", "relative", "user.self", "sys.self"),
|
||
|
order="relative",
|
||
|
replications=20)
|
||
|
print(res)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
##
|
||
|
##
|
||
|
## Old code below. Do not use in new projects, it is here solely for comparison
|
||
|
##
|
||
|
##
|
||
|
|
||
|
|
||
|
## NOTE: This is the old way to compile Rcpp code inline.
|
||
|
## The code here has left as a historical artifact and tribute to the old way.
|
||
|
## Please use the code under the "new" inline compilation section.
|
||
|
|
||
|
rcppGamma_old <- cxxfunction(signature(xs="numeric"), plugin="Rcpp", body='
|
||
|
NumericVector x(xs);
|
||
|
int n = x.size();
|
||
|
|
||
|
RNGScope scope; // Initialize Random number generator. Not needed when Attributes used.
|
||
|
|
||
|
const double y = 1.234;
|
||
|
for (int i=0; i<n; i++) {
|
||
|
x[i] = ::Rf_rgamma(3.0, 1.0/(y*y+4));
|
||
|
}
|
||
|
|
||
|
// Return to R
|
||
|
return x;
|
||
|
')
|
||
|
|
||
|
|
||
|
gslGamma_old <- cxxfunction(signature(xs="numeric"), plugin="RcppGSL",
|
||
|
include='#include <gsl/gsl_rng.h>
|
||
|
#include <gsl/gsl_randist.h>',
|
||
|
body='
|
||
|
NumericVector x(xs);
|
||
|
int n = x.size();
|
||
|
|
||
|
gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);
|
||
|
const double y = 1.234;
|
||
|
for (int i=0; i<n; i++) {
|
||
|
x[i] = gsl_ran_gamma(r,3.0,1.0/(y*y+4));
|
||
|
}
|
||
|
gsl_rng_free(r);
|
||
|
|
||
|
// Return to R
|
||
|
return x;
|
||
|
')
|
||
|
|
||
|
|
||
|
rcppNormal_old <- cxxfunction(signature(xs="numeric"), plugin="Rcpp", body='
|
||
|
NumericVector x(xs);
|
||
|
int n = x.size();
|
||
|
|
||
|
RNGScope scope; // Initialize Random number generator. Not needed when Attributes used.
|
||
|
|
||
|
const double y = 1.234;
|
||
|
for (int i=0; i<n; i++) {
|
||
|
x[i] = ::Rf_rnorm(1.0/(y+1),1.0/sqrt(2*y+2));
|
||
|
}
|
||
|
|
||
|
// Return to R
|
||
|
return x;
|
||
|
')
|
||
|
|
||
|
|
||
|
gslNormal_old <- cxxfunction(signature(xs="numeric"), plugin="RcppGSL",
|
||
|
include='#include <gsl/gsl_rng.h>
|
||
|
#include <gsl/gsl_randist.h>',
|
||
|
body='
|
||
|
NumericVector x(xs);
|
||
|
int n = x.size();
|
||
|
|
||
|
gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);
|
||
|
const double y = 1.234;
|
||
|
for (int i=0; i<n; i++) {
|
||
|
x[i] = 1.0/(y+1)+gsl_ran_gaussian(r,1.0/sqrt(2*y+2));
|
||
|
}
|
||
|
gsl_rng_free(r);
|
||
|
|
||
|
// Return to R
|
||
|
return x;
|
||
|
')
|