part i: introduction - aalborg...

156
Intro Why Tools R API C++ Rcpp Tutorial Part I: Introduction Dr. Dirk Eddelbuettel [email protected] [email protected] useR! 2012 Vanderbilt University June 12, 2012 Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro Intro Why Tools R API C++ So what are we doing today? The high-level motivation The three main questions for the course are: Why? There are several reasons discussed next ... How? We will cover that in detail later today ... What? This will also be covered ... Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Upload: others

Post on 17-Jan-2020

18 views

Category:

Documents


0 download

TRANSCRIPT

Intro Why Tools R API C++

Rcpp TutorialPart I: Introduction

Dr. Dirk [email protected]

[email protected]

useR! 2012Vanderbilt University

June 12, 2012

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++

So what are we doing today?The high-level motivation

The three main questions for the course are:

Why? There are several reasons discussed next ...How? We will cover that in detail later today ...What? This will also be covered ...

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++

Before the Why/How/WhatMaybe some mutual introductions?

How about a really quick round of intros with

Your name and background (academic, industry, ...)R experience (beginner, intermediate, advanced, ...)Created / modified any R packages ?C and/or C++ experience ?Main interest in Rcpp: speed, extension, ...,Following rcpp-devel and/or r-devel ?

but any such disclosure is of course strictly voluntary.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++

Examples

A tar file name RcppWorkshopExamples.tar.gz (as well asa corresponding zip file) containing all examples is at

http://dirk.eddelbuettel.com/code/rcpp/

https://www.dropbox.com/sh/jh3fdxfd918i93n/4OxSkkKLWT

from where you should be able to download it.

We also have copies on USB drives.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

A Simple ExampleCourtesy of Greg Snow via r-help during Sep 2010: examples/part1/gregEx1.R

xx <- faithful$eruptionsfit <- density(xx)plot(fit)

1 2 3 4 5 6

0.0

0.1

0.2

0.3

0.4

0.5

density.default(x = xx)

N = 272 Bandwidth = 0.3348

Den

sity

Standard R use: load some data, estimate a density, plot it.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

A Simple ExampleNow more complete: examples/part1/gregEx2.R

xx <- faithful$eruptionsfit1 <- density(xx)fit2 <- replicate(10000, {x <- sample(xx,replace=TRUE);density(x, from=min(fit1$x),

to=max(fit1$x))$y})fit3 <- apply(fit2, 1,quantile,c(0.025,0.975))

plot(fit1, ylim=range(fit3))polygon(c(fit1$x,rev(fit1$x)),c(fit3[1,], rev(fit3[2,])),col=’grey’, border=F)

lines(fit1)

1 2 3 4 5 6

0.0

0.1

0.2

0.3

0.4

0.5

density.default(x = xx)

N = 272 Bandwidth = 0.3348

Den

sity

What other language can do that in seven statements?

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

MotivationWhy would extending R via C/C++/Rcpp be of interest?

Chambers. Software forData Analysis:Programming with R.Springer, 2008

Chambers (2008) opens chapter 11 (Interfaces I:Using C and Fortran) with these words:

Since the core of R is in fact a programwritten in the C language, it’s not surprisingthat the most direct interface to non-Rsoftware is for code written in C, or directlycallable from C. All the same, includingadditional C code is a serious step, withsome added dangers and often a substantialamount of programming and debuggingrequired. You should have a good reason.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

MotivationWhy would extending R via C/C++/Rcpp be of interest?

Chambers. Software forData Analysis:Programming with R.Springer, 2008

Chambers (2008) opens chapter 11 (Interfaces I:Using C and Fortran) with these words:

Since the core of R is in fact a programwritten in the C language, it’s not surprisingthat the most direct interface to non-Rsoftware is for code written in C, or directlycallable from C. All the same, includingadditional C code is a serious step, withsome added dangers and often asubstantial amount of programming anddebugging required. You should have agood reason.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

MotivationWhy would extending R via C/C++/Rcpp be of interest?

Chambers proceeds with this rough map of the road ahead:

Against:

It’s more workBugs will bitePotential platformdependencyLess readable software

In Favor:

New and trustedcomputationsSpeedObject references

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

So the why...

The why boils down to:

speed! Often a good enough reason for us ... and a majorfocus for us today.new things! We can bind to libraries and tools that wouldotherwise be unavailablereferences! Chambers quote from 2008 somehowforeshadowed the work on the new Reference Classesreleased with R 2.12 and which work very well with Rcppmodules. More on that this afternoon.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

First speed exampleexamples/part1/straightCurly.R

A blog post two summers ago discussed how R’s internalparser could be improved.

It repeatedly evaluated 11+x using

## Xian’s code, using <- for assignments and passing x downf <- function(n, x=1) for (i in 1:n) x=1/(1+x)g <- function(n, x=1) for (i in 1:n) x=(1/(1+x))h <- function(n, x=1) for (i in 1:n) x=(1+x)^(-1)j <- function(n, x=1) for (i in 1:n) x={1/{1+x}}k <- function(n, x=1) for (i in 1:n) x=1/{1+x}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

First speed example (cont.)examples/part1/straightCurly.R

We can use this to introduce tools such as rbenchmark:

# now load some toolslibrary(rbenchmark)

# now run the benchmarkN <- 1e5benchmark(f(N,1), g(N,1), h(N,1), j(N,1), k(N,1),

columns=c("test", "replications","elapsed", "relative"),

order="relative", replications=10)

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

First speed example (cont.)examples/part1/straightCurly.R

R> N <- 1e5R> benchmark(f(N,1),g(N,1),h(N,1),j(N,1),k(N,1),+ columns=c("test", "replications",+ "elapsed", "relative"),+ order="relative", replications=10)

test replications elapsed relative5 k(N, 1) 10 0.961 1.000001 f(N, 1) 10 0.970 1.009374 j(N, 1) 10 1.052 1.094692 g(N, 1) 10 1.144 1.190433 h(N, 1) 10 1.397 1.45369R>

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

First speed example: Now with C++examples/part1/straightCurly.R

So let us add Rcpp to the mix and show inline too:

## now with Rcpp and C++library(inline)

# and define our version in C++src <- ’int n = as<int>(ns);

double x = as<double>(xs);for (int i=0; i<n; i++) x=1/(1+x);return wrap(x); ’

l <- cxxfunction(signature(ns="integer",xs="numeric"),

body=src, plugin="Rcpp")

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

First speed example: Now with C++examples/part1/straightCurly.R

The key line is almost identical to what we would do in R

## now with Rcpp and C++library(inline)

# and define our version in C++src <- ’int n = as<int>(ns);

double x = as<double>(xs);for (int i=0; i<n; i++) x=1/(1+x);return wrap(x); ’

l <- cxxfunction(signature(ns="integer",xs="numeric"),

body=src, plugin="Rcpp")

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

First speed example: Now with C++examples/part1/straightCurly.R

Data input and output is not too hard:

## now with Rcpp and C++library(inline)

# and define our version in C++src <- ’int n = as<int>(ns);

double x = as<double>(xs);for (int i=0; i<n; i++) x=1/(1+x);return wrap(x); ’

l <- cxxfunction(signature(ns="integer",xs="numeric"),

body=src, plugin="Rcpp")

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

First speed example: Now with C++examples/part1/straightCurly.R

And compiling, linking and loading is a single function call:

## now with Rcpp and C++library(inline)

# and define our version in C++src <- ’int n = as<int>(ns);

double x = as<double>(xs);for (int i=0; i<n; i++) x=1/(1+x);return wrap(x); ’

l <- cxxfunction(signature(ns="integer",xs="numeric"),

body=src, plugin="Rcpp")

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

First speed example: Now with C++examples/part1/straightCurly.R

R> # now run the benchmark againR> benchmark(f(N,1), g(N,1), h(N,1), j(N,1),+ k(N,1), l(N,1),+ columns=c("test", "replications",+ "elapsed", "relative"),+ order="relative", replications=10)

test replications elapsed relative6 l(N, 1) 10 0.013 1.00001 f(N, 1) 10 0.944 72.61545 k(N, 1) 10 0.944 72.61544 j(N, 1) 10 1.052 80.92312 g(N, 1) 10 1.145 88.07693 h(N, 1) 10 1.425 109.6154R>

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

First speed example: Now with C++examples/part1/straightCurly.R

R> # now run the benchmark againR> benchmark(f(N,1), g(N,1), h(N,1), j(N,1),+ k(N,1), l(N,1),+ columns=c("test", "replications",+ "elapsed", "relative"),+ order="relative", replications=10)

test replications elapsed relative6 l(N, 1) 10 0.013 1.00001 f(N, 1) 10 0.944 72.61545 k(N, 1) 10 0.944 72.61544 j(N, 1) 10 1.052 80.92312 g(N, 1) 10 1.145 88.07693 h(N, 1) 10 1.425 109.6154R>

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Second speed exampleexamples/part1/fibonacci.R

A question on StackOverflow wondered what to do about slowrecursive functions.

The standard definition of the Fibonacci sequence isFn = Fn−1 + Fn−2 with initial values F0 = 0 and F1 = 1.

This leads this intuitive (but slow) R implementation:

## basic R functionfibR <- function(n) {

if (n == 0) return(0)if (n == 1) return(1)return (fibR(n - 1) + fibR(n - 2))

}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Second speed example: Now with C++examples/part1/fibonacci.R

We can write an easy (and very fast) C++ version:

## we need a pure C/C++ function hereincltxt <- ’

int fibonacci(const int x) {if (x == 0) return(0);if (x == 1) return(1);return (fibonacci(x - 1)) + fibonacci(x - 2);

}’

## Rcpp version of FibonaccifibRcpp <- cxxfunction(signature(xs="int"),

plugin="Rcpp",incl=incltxt, body=’

int x = Rcpp::as<int>(xs);return Rcpp::wrap( fibonacci(x) );

’)

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Second speed example: Now with C++examples/part1/fibonacci.R

So just how much faster it the C++ version?R> N <- 35 ## same parameter as original postR> res <- benchmark(fibR(N), fibRcpp(N),+ columns=c("test", "replications", "elapsed",+ "relative", "user.self", "sys.self"),+ order="relative", replications=1)R> print(res) ## show result

test replications elapsed relative user.self sys.self2 fibRcpp(N) 1 0.093 1.00 0.09 01 fibR(N) 1 61.553 661.86 61.35 0

So a six-hundred fold increase for no real effort or setup cost.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

More on speed

Other examples:

The RcppArmadillo, RcppEigen and RcppGSLpackages each contain a fastLM() functionThis is a faster reimplementation of lm(), suitable forrepeated use in Monte CarloArmadillo (and Eigen) make this a breeze: you can dolinear algebra “as you would write it with pen on paper” (butthere are somewhat more technical reasons why youshouldn’t ...)More on that later too.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Another angle on speed

Run-time performance is just one example.

Time to code is another metric.

We feel quite strongly that Rcpp helps you code moresuccinctly, leading to fewer bugs and faster development.

The RcppDE package aims to provide a concrete example ofmaking an existing C implemention shorter, easier and possiblyat the same time also faster. (NB: But the initial speedup mayhave been due to a code review – yet easier and shorter stillapply.)

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Doing new things more easily

Consider the over sixty CRAN packages now using Rcpp.Among those, we find:

RQuantlib QuantLib C++RcppArmadillo Armadillo C++RcppEigen Eigen C++RBrownie Brownie (i.e. phylogenetic) C++RcppGSL GNU GSL CRProtoBuf (Google) Protocol Buffers CRSNNS SNNS (i.e. neural nets) Cmaxent max. entropy library (U Tokyo) C++

A key feature is making it easy to access new functionality bymaking it easy to write wrappers.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Why R? Why extend R? Speed New Refs

S3, S4, and now Reference Classes

The new Reference Classes which appeared with R 2.12.0 areparticularly well suited for multi-lingual work. C++ (via Rcpp)was the first example cited by John Chambers in a nicepresentation at Stanford in the fall of 2010.

More in the afternoon...

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Some Preliminaries on Tools

Use a recent version of R (>= 2.12.0 for ReferenceClasses; >= 2.13.0 for the R compiler package).Examples shown should work ’as is’ on Unix-alike OSs;most will also work on Windows provided a complete Rdevelopment environmentR Installation and Administration is an excellent start toaddress the preceding point (if need be)We will compile code, so Rtools, or X Code, or standardLinux dev tools, are required.using namespace Rcpp; may be implied in someexamples.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Work on Windows too – with some extra care

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Work on Windows too – R CMD INSTALL as a test

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

A Tradition to follow: Hello, world!examples/part1/ex1.cpp

Let us start with some basic tool use.

Consider this simple C++ example:

#include <cstdio>

int main(void) {printf("Hello, World!\n");

}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

A Tradition to follow: Hello, world!Building and running: examples/part1/ex1.cpp

We can now build the program by invoking g++.

$ g++ -o ex1 ex1.cpp$ ./ex1Hello, World!$

This use requires only one option to g++ to select the name ofthe resulting output file.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Accessing external libraries and headersAn example using the R Math library: examples/part1/ex2.cpp

This example uses a function from the standalone R library :

#include <cstdio>#define MATHLIB_STANDALONE#include <Rmath.h>

int main(void) {printf("N(0,1) 95th percentile %9.8f\n",qnorm(0.95, 0.0, 1.0, 1, 0));

}

We declare the function via the header file (as well as defininga variable before loading, see ’Writing R Extensions’) and thenneed to provide a suitable library to link to.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Accessing external libraries and headersAn example using the R Math library: examples/part1/ex2.cpp

We use -I/some/dir to point to a header directory, and-L/other/dir -lfoo to link with an external library locatedin a particular directory.

$ g++ -I/usr/include -c ex2.cpp$ g++ -o ex2 ex2.o -L/usr/lib -lRmath$ ./ex2N(0,1) 95th percentile 1.64485363$

This can be tedious as header and library locations may varyacross machines or installations. Automated detection is key.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Building an R moduleexamples/part1/modEx1.cpp

Building a dynamically callable module to be used by R issimilar to the direct compilation.

#include <R.h>#include <Rinternals.h>

extern "C" SEXP helloWorld(void) {Rprintf("Hello, World!\n");return R_NilValue;

}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Building an R moduleexamples/part1/modEx1.cpp

We use R to compile and build this:

$ R CMD SHLIB modEx1.cppg++ -I/usr/share/R/include -fpic -O3 \

-g -c modEx1.cpp -o modEx1.og++ -shared -o modEx1.so \

modEx1.o -L/usr/lib64/R/lib -lR$

R can select the -I and -L flags appropriately as it knows itsheader and library locations.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Running the R moduleexamples/part1/modEx1.cpp

We load the shared library and call the function via .Call:

R> dyn.load("modEx1.so")R> .Call("helloWorld")Hello, World!NULLR>

Other operating systems may need a different file extension.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

R CMD SHLIB options

R CMD SHLIB can take linker options.

Using the variables PKG_CXXFLAGS and PKG_LIBS, we canalso select headers and libraries — which we’ll look at withRcpp below.

But this gets tedious fast (and example is in the next section).

Better options will be shown later.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Rcpp and R CMD SHLIBexamples/part1/modEx2.cpp

Let us (re-)consider the first Rcpp example from above. In astandalone file it looks like this:

#include <Rcpp.h>using namespace Rcpp;

RcppExport SEXP modEx2(SEXP ns, SEXP xs) {int n = as<int>(ns);double x = as<double>(xs);

for (int i=0; i<n; i++)x=1/(1+x);

return wrap(x);}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Rcpp and R CMD SHLIBexamples/part1/modEx2.cpp

We use PKG_CPPFLAGS and PKG_LIBS to tell R whichheaders and libraries. Here we let Rcpp tell us:

$ export PKG_CPPFLAGS=‘Rscript -e ’Rcpp:::CxxFlags()’‘$ export PKG_LIBS=‘Rscript -e ’Rcpp:::LdFlags()’‘$ R CMD SHLIB modEx2.cppg++ -I/usr/share/R/include \

-I/usr/local/lib/R/site-library/Rcpp/include \-fpic -O3 -pipe -g -c modEx2.cpp -o modEx2.o

g++ -shared -o modEx2.so modEx2.o \-L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp \-Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib \-L/usr/lib64/R/lib -lR

Note the result arguments—it is helpful to understand whateach part is about. Here we add the Rcpp library as well asinformation for the dynamic linker about where to find the libraryat run-time.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

Outline

1 Introduction

2 Why? The Main MotivationWhy R?Why extend R?SpeedNew ThingsReferences

3 How? The ToolsPreliminariesCompiling and LinkingR CMD SHLIBRcppinline

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

inline

inline makes compiling, linking and loading a lot easier. Asseen above, all it takes is a single call:

src <- ’int n = as<int>(ns);double x = as<double>(xs);for (int i=0; i<n; i++) x=1/(1+x);return wrap(x); ’

l <- cxxfunction(signature(ns="integer",xs="numeric"),

body=src, plugin="Rcpp")

No more manual -I and -L — inline takes over.

It also allows us to pass extra -I and -L arguments for otherlibraries. An (old) example using GNU GSL (which predates theRcppGSL package) follows:

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

inline – with external libraries tooexamples/part1/gslRng.R

## a really simple C++ program calling functions from the GSLsrc <- ’int seed = Rcpp::as<int>(par) ;

gsl_rng_env_setup();gsl_rng *r = gsl_rng_alloc (gsl_rng_default);gsl_rng_set (r, (unsigned long) seed);double v = gsl_rng_get (r);gsl_rng_free(r);return Rcpp::wrap(v); ’

## turn into a function that R can callfun <- cfunction(signature(par="numeric"), body=src,

includes="#include <gsl/gsl_rng.h>",Rcpp=TRUE,cppargs="-I/usr/include",libargs="-lgsl -lgslcblas")

(RcppGSL offers a plugin to cxxfunction() which alleviatesfour of the arguments to cfunction here.)

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Prelim Linking R CMD Rcpp inline

inline also good for heavily templated codeWhit’s rcpp-devel post last fall: examples/part1/whit.R

library(inline)library(Rcpp)

inc <- ’#include <iostream>#include <armadillo>#include <cppbugs/cppbugs.hpp>

using namespace arma;using namespace cppbugs;

class TestModel: public MCModel {public:const mat &y, &x; // given

Normal<vec> b;Uniform<double> tau_y;Deterministic<mat> y_hat;Normal<mat> likelihood;Deterministic<double> rsq;

TestModel(const mat& y_,const mat& X_):y(y_), X(X_), b(randn<vec>(X_.n_cols)),tau_y(1), y_hat(X*b.value),likelihood(y_,true), rsq(0)

{add(b); add(tau_y); add(y_hat);add(likelihood); add(rsq);

}// [....and more ...]’

The inc=inc argument tocxxfunction canincludes headers beforethe body=src part.

And the templatedCppBUGS package by Whitnow easily outperformsPyMC / Bugs.

And is still easilyaccessible from R.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

Outline

4 The R APIOverviewFirst Example: Operations on VectorsSecond Example: Operations on CharactersThird Example: Calling an R functionFourth Example: Creating a list

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

R support for C/C++

R is a C program, and C programs can be extendedR exposes an API with C functions and MACROSR also supports C++ out of the box: use .cpp extensionR provides several calling conventions:

.C() provided the first interface, is fairly limited and nolonger recommended.Call() provides access to R objects at the C level.External() and .Fortran exist but can be ignored

so we will use .Call() exclusively.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

R API via .Call()

At the C level, everything is a SEXP, and all functionscorrespond to this interface:

SEXP foo( SEXP x1, SEXP x2 ){...

}

which can be called from R via.Call("foo", var1, var2)

and more examples will follow.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

Outline

4 The R APIOverviewFirst Example: Operations on VectorsSecond Example: Operations on CharactersThird Example: Calling an R functionFourth Example: Creating a list

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

A simple function on vectorsexamples/part1/R_API_ex1.cpp

Can you guess what this does?#include <R.h>#include <Rdefines.h>extern "C" SEXP vectorfoo(SEXP a, SEXP b){

int i, n;double *xa, *xb, *xab; SEXP ab;PROTECT(a = AS_NUMERIC(a));PROTECT(b = AS_NUMERIC(b));n = LENGTH(a);PROTECT(ab = NEW_NUMERIC(n));xa=NUMERIC_POINTER(a); xb=NUMERIC_POINTER(b);xab = NUMERIC_POINTER(ab);double x = 0.0, y = 0.0 ;for (i=0; i<n; i++) xab[i] = 0.0;for (i=0; i<n; i++) {x = xa[i]; y = xb[i];res[i] = (x < y) ? x*x : -(y*y);

}UNPROTECT(3);return(ab);

}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

A simple function on vectorsexamples/part1/R_API_ex1.cpp

The core computation is but a part:#include <R.h>#include <Rdefines.h>extern "C" SEXP vectorfoo(SEXP a, SEXP b){

int i, n;double *xa, *xb, *xab; SEXP ab;PROTECT(a = AS_NUMERIC(a));PROTECT(b = AS_NUMERIC(b));n = LENGTH(a);PROTECT(ab = NEW_NUMERIC(n));xa=NUMERIC_POINTER(a); xb=NUMERIC_POINTER(b);xab = NUMERIC_POINTER(ab);

double x = 0.0, y = 0.0 ;for (i=0; i<n; i++) xab[i] = 0.0;for (i=0; i<n; i++) {

x = xa[i]; y = xb[i];res[i] = (x < y) ? x*x : -(y*y);

}UNPROTECT(3);return(ab);

}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

A simple function on vectorsexamples/part1/R_API_ex1.cpp

Memory management is both explicit, tedious and error-prone:#include <R.h>#include <Rdefines.h>extern "C" SEXP vectorfoo(SEXP a, SEXP b){

int i, n;double *xa, *xb, *xab; SEXP ab;PROTECT(a = AS_NUMERIC(a));PROTECT(b = AS_NUMERIC(b));

n = LENGTH(a);PROTECT(ab = NEW_NUMERIC(n));

xa=NUMERIC_POINTER(a); xb=NUMERIC_POINTER(b);xab = NUMERIC_POINTER(ab);double x = 0.0, y = 0.0 ;for (i=0; i<n; i++) xab[i] = 0.0;for (i=0; i<n; i++) {x = xa[i]; y = xb[i];res[i] = (x < y) ? x*x : -(y*y);

}UNPROTECT(3);

return(ab);}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

Outline

4 The R APIOverviewFirst Example: Operations on VectorsSecond Example: Operations on CharactersThird Example: Calling an R functionFourth Example: Creating a list

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

A simple function on character vectorsexamples/part1/R_API_ex2.cpp

In R , we simply use

c( "foo", "bar" )

whereas the C API requires

#include <R.h>#include <Rdefines.h>extern "C" SEXP foobar(){

SEXP res = PROTECT(allocVector(STRSXP, 2));SET_STRING_ELT( res, 0, mkChar( "foo" ) ) ;SET_STRING_ELT( res, 1, mkChar( "bar" ) ) ;UNPROTECT(1) ;return res ;

}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

Outline

4 The R APIOverviewFirst Example: Operations on VectorsSecond Example: Operations on CharactersThird Example: Calling an R functionFourth Example: Creating a list

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

Calling an R functionexamples/part1/R_API_ex2.cpp

In R , we call

rnorm(3L, 10.0, 20.0)

but in C this becomes#include <R.h>#include <Rdefines.h>extern "C" SEXP callback(){

SEXP call = PROTECT( LCONS( install("rnorm"),CONS( ScalarInteger( 3 ),CONS( ScalarReal( 10.0 ),

CONS( ScalarReal( 20.0 ), R_NilValue ))

)) );SEXP res = PROTECT(eval(call, R_GlobalEnv)) ;UNPROTECT(2) ;return res ;

}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

Outline

4 The R APIOverviewFirst Example: Operations on VectorsSecond Example: Operations on CharactersThird Example: Calling an R functionFourth Example: Creating a list

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Vectors Characters R Code List

Fourth Example: Listsexamples/part1/R_API_ex4.cpp

#include <R.h>#include <Rdefines.h>

extern "C" SEXP listex(){SEXP res = PROTECT( allocVector( VECSXP, 2 ) ) ;SEXP x1 = PROTECT( allocVector( REALSXP, 2 ) ) ;SEXP x2 = PROTECT( allocVector( INTSXP, 2 ) ) ;SEXP names = PROTECT( mkString( "foobar" ) ) ;

double* px1 = REAL(x1) ; px1[0] = 0.5 ; px1[1] = 1.5 ;int* px2 = INTEGER(x2); px2[0] = 2 ; px2[1] = 3 ;

SET_VECTOR_ELT( res, 0, x1 ) ;SET_VECTOR_ELT( res, 1, x2 ) ;setAttrib( res, install("class"), names ) ;

UNPROTECT(4) ;return res ;

}

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Outline

5 C++ for R ProgrammersOverviewCompiledStatic TypingBetter CObject-OrientationGeneric Programming and the STLTemplate Programming

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

C++ for R programmers

C++ is a large and sometimes complicated language.

We cannot introduce it in just a few minutes, but will will providea number of key differences—relative to R which should be acommon point of departure.

So on the next few slides, we will highlight just a few keydifferences, starting with big-picture differene with between Rand C/C++.

One view we like comes from Meyers: C++ is a federation offour languages. We will also touch upon each of these fourlanguages.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Outline

5 C++ for R ProgrammersOverviewCompiledStatic TypingBetter CObject-OrientationGeneric Programming and the STLTemplate Programming

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Compiled rather than interpreted

We discussed this already in the context of the toolchain.

Programs need to be compiled first. This may require access toheader files defining interfaces to other projects.

After compiling into object code, the object is linked into anexecutable, possibly together with other libraries.

There is a difference between static and dynamic linking.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Outline

5 C++ for R ProgrammersOverviewCompiledStatic TypingBetter CObject-OrientationGeneric Programming and the STLTemplate Programming

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Static typing

R is dynamically typed: x <- 3.14; x <- "foo" is valid.

In C++, each variable must be declared before first use.

Common types are int and long (possibly with unsigned),float and double, bool, as well as char.

No standard string type, though std::string comes close.

All these variables types are scalars which is fundamentallydifferent from R where everything is a vector (possibly of lengthone).

class (and struct) allow creation of composite types;classes add behaviour to data to form objects.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Outline

5 C++ for R ProgrammersOverviewCompiledStatic TypingBetter CObject-OrientationGeneric Programming and the STLTemplate Programming

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

C++ is a better C — with similarities to R

control structures similar to what R offers: for, while, if,switch

functions are similar too but note the difference inpositional-only matching, also same function name butdifferent arguments allowed in C++pointers and memory management: very different, but lotsof issues folks had with C can be avoided via STL (which issomething Rcpp promotes too)that said, it is still useful to know what a pointer is ...

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Outline

5 C++ for R ProgrammersOverviewCompiledStatic TypingBetter CObject-OrientationGeneric Programming and the STLTemplate Programming

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Object-oriented programming

This is a second key feature of C++, and it does it differentlyfrom S3 and S4 (but closer to the new Reference Classes).Let’s look at an example:

struct Date {unsigned int yearunsigned int month;unsigned int date;

};

struct Person {char firstname[20];char lastname[20];struct Date birthday;unsigned long id;

};

These are just nested data structures.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Object-oriented programming

OO in the C++ sense marries data with code to operate on it:

class Date {private:

unsigned int yearunsigned int month;unsigned int date;

public:void setDate(int y, int m, int d);int getDay();int getMonth();int getYear();

}

Here the data is hidden, access to get / set is provided via an interface.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Outline

5 C++ for R ProgrammersOverviewCompiledStatic TypingBetter CObject-OrientationGeneric Programming and the STLTemplate Programming

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Standard Template Library: Containers

The STL promotes generic programming via an efficientimplementation.

For example, the sequence container types vector, deque,and list all support

push_back() to insert at the end;pop_back() to remove from the front;begin() returning an iterator to the first element;end() returning an iterator to just after the last element;size() for the number of elements;

but only list has push_front() and pop_front().

Other useful containers: set, multiset, map and multimap.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Standard Template Library: Iterators and Algorithms

Traversal of containers can be achieved via iterators whichrequire suitable member functions begin() and end():std::vector<double>::const_iterator si;for (si=s.begin(); si != s.end(); si++)

std::cout << *si << std::endl;

Another key STL part are algorithms:double sum = accumulate(s.begin(), s.end(), 0);

Other popular STL algorithms arefind finds the first element equal to the supplied value

count counts the number of matching elementstransform applies a supplied function to each elementfor_each sweeps over all elements, does not alterinner_product inner product of two vectors

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Outline

5 C++ for R ProgrammersOverviewCompiledStatic TypingBetter CObject-OrientationGeneric Programming and the STLTemplate Programming

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Template Programming

Template programming provides the last ’language within C++’.One of the simplest template examples istemplate <typename T>const T& min(const T& x, const T& y) {

return y < x ? y : x;}

This can now be used to compute the minimum between twoint variables, or double, or in fact any admissible typeproviding an operator<() for less-than comparison.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Intro Why Tools R API C++ Overview Compiled Static Better C OO STL TP

Template Programming

Another template example is a class squaring its argument:template <typename T>class square : public std::unary_function<T,T> {public:

T operator()( T t) const {return t*t;

}};

which can be used along with some of the STL algorithms. Forexample, given an object x that has iterators, then

transform(x.begin(), x.end(), square);

squares all its elements in-place.

Dirk Eddelbuettel Rcpp Tutorial — Part I: Intro

Classes Extending package

Rcpp TutorialPart II: Rcpp Details

Dr. Dirk [email protected]

[email protected]

useR! 2012Vanderbilt University

June 12, 2012

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Outline

1 Main Rcpp ClassesRObjectIntegerVectorNumericVectorGenericVectorDataFrameFunctionEnvironmentsS4

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

RObject

The RObject class is the basic class behind the Rcpp API.

It provides a thin wrapper around a SEXP object—this issometimes called a proxy object as we do not copy the Robject.

RObject manages the life cycle, the object is protected fromgarbage collection while in scope—so you do not have to domemory management.

RObject defines several member functions common to allobjects (e.g., isS4(), attributeNames, ...); derived classesthen define specific member functions.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Overview of classes: Comparison

Rcpp class R typeofInteger(Vector|Matrix) integer vectors and matricesNumeric(Vector|Matrix) numeric ...Logical(Vector|Matrix) logical ...Character(Vector|Matrix) character ...

Raw(Vector|Matrix) raw ...Complex(Vector|Matrix) complex ...

List list (aka generic vectors) ...Expression(Vector|Matrix) expression ...

Environment environmentFunction function

XPtr externalptrLanguage language

S4 S4... ...

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Overview of key vector / matrix classes

IntegerVector vectors of type integer

NumericVector vectors of type numeric

RawVector vectors of type raw

LogicalVector vectors of type logical

CharacterVector vectors of type character

GenericVector generic vectors implementing list types

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Common core functions for Vectors and Matrices

Key operations for all vectors, styled after STL operations:

operator() access elements via ()

operator[] access elements via []

length() also aliased to size()

fill(u) fills vector with value of ubegin() pointer to beginning of vector, for iteratorsend() pointer to one past end of vector

push_back(x) insert x at end, grows vectorpush_front(x) insert x at beginning, grows vectorinsert(i, x) insert x at position i, grows vectorerase(i) remove element at position i, shrinks vector

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Outline

1 Main Rcpp ClassesRObjectIntegerVectorNumericVectorGenericVectorDataFrameFunctionEnvironmentsS4

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

A first exampleexamples/part2/intVecEx1.R

Let us reimplement (a simpler version of) prod() for integervectors:

library(inline)

src <- ’Rcpp::IntegerVector vec(vx);int prod = 1;for (int i=0; i<vec.size(); i++) {

prod *= vec[i];}return Rcpp::wrap(prod);

’fun <- cxxfunction(signature(vx="integer"),

src, plugin="Rcpp")fun(1L:10L)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Passing data from from Rexamples/part2/intVecEx1.R

We instantiate the IntegerVector object with the SEXPreceived from R :

library(inline)

src <- ’Rcpp::IntegerVector vec(vx);int prod = 1;for (int i=0; i<vec.size(); i++) {

prod *= vec[i];}return Rcpp::wrap(prod);

’fun <- cxxfunction(signature(vx="integer"),

src, plugin="Rcpp")fun(1L:10L)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Objects tell us their sizeexamples/part2/intVecEx1.R

The loop counter can use the information from theIntegerVector itself:

library(inline)

src <- ’Rcpp::IntegerVector vec(vx);int prod = 1;for (int i=0; i<vec.size(); i++) {

prod *= vec[i];}return Rcpp::wrap(prod);

’fun <- cxxfunction(signature(vx="integer"),

src, plugin="Rcpp")fun(1L:10L)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Element accessexamples/part2/intVecEx1.R

We simply access elements by index (but note that the range isover 0 . . .N − 1 as is standard for C and C++):

library(inline)

src <- ’Rcpp::IntegerVector vec(vx);int prod = 1;for (int i=0; i<vec.size(); i++) {

prod *= vec[i];}return Rcpp::wrap(prod);

’fun <- cxxfunction(signature(vx="integer"),

src, plugin="Rcpp")fun(1L:10L)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Returning resultsexamples/part2/intVecEx1.R

We return the scalar int by using the wrap helper:

library(inline)

src <- ’Rcpp::IntegerVector vec(vx);int prod = 1;for (int i=0; i<vec.size(); i++) {

prod *= vec[i];}return Rcpp::wrap(prod);

’fun <- cxxfunction(signature(vx="integer"),

src, plugin="Rcpp")fun(1L:10L)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

An STL variantexamples/part2/intVecEx2.R

As an alternative, the Standard Template Library also allows usa loop-less variant similar in spirit to vectorised R expressions:

library(inline)

src <- ’Rcpp::IntegerVector vec(vx);int prod = std::accumulate(vec.begin(), vec.end(),

1, std::multiplies<int>());return Rcpp::wrap(prod);

’fun <- cxxfunction(signature(vx="integer"),

src, plugin="Rcpp")fun(1L:10L)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Outline

1 Main Rcpp ClassesRObjectIntegerVectorNumericVectorGenericVectorDataFrameFunctionEnvironmentsS4

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

A first exampleexamples/part2/numVecEx1.R

NumericVector is very similar to IntegerVector.Here is an example generalizing sum of squares by supplyingan exponentiation argument:

src <- ’Rcpp::NumericVector vec(vx);double p = Rcpp::as<double>(dd);double sum = 0.0;for (int i=0; i<vec.size(); i++) {

sum += pow(vec[i], p);}return Rcpp::wrap(sum); ’

fun <- cxxfunction(signature(vx="numeric",dd="numeric"),

src, plugin="Rcpp")fun(1:4,2)fun(1:4,2.2)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

A second exampleRemember to clone: examples/part2/numVecEx2.R

R> src <- ’+ NumericVector x1(xs);+ NumericVector x2(Rcpp::clone(xs));+ x1[0] = 22;+ x2[1] = 44;+ return(DataFrame::create(Named("orig", xs),+ Named("x1", x1),+ Named("x2", x2)));’R> fun <- cxxfunction(signature(xs="numeric"),+ body=src, plugin="Rcpp")R> fun(seq(1.0, 3.0, by=1.0))

orig x1 x21 22 22 12 2 2 443 3 3 3R>

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

A second example: continuedSo why is the second case different? examples/part2/numVecEx2.R

Understanding why these two examples perform differently isimportant:R> fun(seq(1.0, 3.0, by=1.0))

orig x1 x21 22 22 12 2 2 443 3 3 3R> fun(1L:3L)

orig x1 x21 1 22 12 2 2 443 3 3 3R>

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Constructor overviewFor NumericVector and other vectors deriving from RObject

SEXP x;NumericVector y( x ); // from a SEXP

// cloning (deep copy)NumericVector z = clone<NumericVector>( y );

// of a given size (all elements set to 0.0)NumericVector y( 10 );

// ... specifying the valueNumericVector y( 10, 2.0 );

// ... with elements generatedNumericVector y( 10, ::Rf_unif_rand );

// with given elementsNumericVector y = NumericVector::create( 1.0, 2.0 );

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Matricesexamples/part2/numMatEx1.R

NumericMatrix is a specialisation of NumericVector whichuses a dimension attribute:

src <- ’Rcpp::NumericVector mat =

Rcpp::clone<Rcpp::NumericMatrix>(mx);std::transform(mat.begin(), mat.end(),

mat.begin(), ::sqrt);return mat; ’

fun <- cxxfunction(signature(mx="numeric"), src,plugin="Rcpp")

orig <- matrix(1:9, 3, 3)fun(orig)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Matrices: RcppArmadillo for mathexamples/part2/numMatEx3.R

However, Armadillo is an excellent C++ choice for linearalgebra, and RcppArmadillo makes this very easy to use:src <- ’

arma::mat m1 = Rcpp::as<arma::mat>(mx);arma::mat m2 = m1 + m1;arma::mat m3 = m1 * 2;return Rcpp::List::create(m1, m2, m3); ’

fun <- cxxfunction(signature(mx="numeric"), src,plugin="RcppArmadillo")

mat <- matrix(1:9, 3, 3)fun(mat)

We will say more about RcppArmadillo later.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Other vector types

LogicalVector is very similar to IntegerVector as itrepresent the two possible values of a logical, or boolean, type.These values—True and False—can also be mapped to oneand zero (or even a more general ’not zero’ and zero).

The class CharacterVector can be used for vectors of Rcharacter vectors (“strings”).

The class RawVector can be used for vectors of raw strings.

Named can be used to assign named elements in a vector,similar to the R construct a <- c(foo=3.14, bar=42)letting us set attribute names (example below); "_" is ashortcut alternative we will see in a few examples.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Outline

1 Main Rcpp ClassesRObjectIntegerVectorNumericVectorGenericVectorDataFrameFunctionEnvironmentsS4

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

GenericVector class (aka List) to receive values

We can use the List type to receive parameters from R . Thisis an example from the RcppExamples package:

RcppExport SEXP newRcppParamsExample(SEXP params) {

Rcpp::List rparam(params); // Get parameters in params.std::string method = Rcpp::as<std::string>(rparam["method"]);double tolerance = Rcpp::as<double>(rparam["tolerance"]);int maxIter = Rcpp::as<int>(rparam["maxIter"]);[...]

A List is initialized from a SEXP; elements are looked up byname as in R .Lists can be nested too, and may contain other SEXP types too.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

GenericVector class (aka List) to return values

We can also use the List type to send results from R . This isan example from the RcppExamples package:

return Rcpp::List::create(Rcpp::Named("method", method),Rcpp::Named("tolerance", tolerance),Rcpp::Named("maxIter", maxIter),Rcpp::Named("startDate", startDate),Rcpp::Named("params", params));

This uses the create method to assemble a List object. Weuse Named to pair each element (which can be anythingwrap’able to SEXP) with a name.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Outline

1 Main Rcpp ClassesRObjectIntegerVectorNumericVectorGenericVectorDataFrameFunctionEnvironmentsS4

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

DataFrame classexamples/part2/dataFrameEx1.R

The DataFrame class be used to receive and return values.On input, we can extract columns from a data frame; row-wiseaccess is not possible.

src <- ’Rcpp::IntegerVector v =

Rcpp::IntegerVector::create(1,2,3);std::vector<std::string> s(3);s[0] = "a";s[1] = "b";s[2] = "c";return Rcpp::DataFrame::create(Rcpp::Named("a")=v,

Rcpp::Named("b")=s);’fun <- cxxfunction(signature(), src, plugin="Rcpp")fun()

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Outline

1 Main Rcpp ClassesRObjectIntegerVectorNumericVectorGenericVectorDataFrameFunctionEnvironmentsS4

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Function: First exampleexamples/part2/functionEx1.R

Functions are another types of SEXP object we can represent:

src <- ’Function s(x) ;return s( y, Named("decreasing", true));’

fun <- cxxfunction(signature(x="function",y="ANY"),

src, plugin="Rcpp")fun(sort, sample(1:5, 10, TRUE))fun(sort, sample(LETTERS[1:5], 10, TRUE))

The R function sort is used to instantiate a C++ objects—which we feed the second argument as well as another Rexpression created on the spot as decreasing=TRUE.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Function: Second exampleexamples/part2/functionEx1.R

We can use the Function class to access R functions:src <- ’

Rcpp::Function rt("rt");return rt(5, 3);

’fun <- cxxfunction(signature(),

src, plugin="Rcpp")set.seed(42)fun()

The R function rt() is access directly and used to instantiatea C++ object of the same name—which we get draw fiverandom variable with three degrees of freedom.While convenient, there is overhead—so we prefer functionsavailable with ’Rcpp sugar’ (discussed later).

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Outline

1 Main Rcpp ClassesRObjectIntegerVectorNumericVectorGenericVectorDataFrameFunctionEnvironmentsS4

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Environmentsexamples/part2/environmentEx1.R

The Environment class helps us access R environments.

src <- ’Rcpp::Environment stats("package:stats");Rcpp::Function rnorm = stats["rnorm"];return rnorm(10, Rcpp::Named("sd", 100.0));

fun <- cxxfunction(signature(),src, plugin="Rcpp")

fun()

The environement of the (base) package stats is instantiated,and we access the rnorm() function from it. This is analternative to accessing build-in functions. (But note that thereis also overhead in calling R functions this way.)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

Outline

1 Main Rcpp ClassesRObjectIntegerVectorNumericVectorGenericVectorDataFrameFunctionEnvironmentsS4

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package RObject integer numeric list list function env S4

S4examples/part2/S4ex1.R

S4 classes can also be created, or altered, at the C++ level.

src <- ’S4 foo(x) ;foo.slot(".Data") = "bar" ;return(foo);

’fun <- cxxfunction(signature(x="any"), src,

plugin="Rcpp")setClass( "S4ex", contains = "character",

representation( x = "numeric" ) )x <- new( "S4ex", "bla", x = 10 )fun(x)str(fun(x))

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Outline

2 Extending Rcpp via as and wrapIntroductionExtending wrapExtending asExample

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

as() and wrap()

as() and wrap() are key components of the R and C++ datainterchange.

They are declared as

// conversion from R to C++template <typename T>T as( SEXP m_sexp) throw(not_compatible);

// conversion from C++ to Rtemplate <typename T>SEXP wrap(const T& object);

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

as and wrap usage exampleexamples/part2/asAndWrapEx1.R

code <- ’// we get a list from RRcpp::List input(inp);// pull std::vector<double> from R list// via an implicit call to Rcpp::asstd::vector<double> x = input["x"] ;// return an R list// via an implicit call to Rcpp::wrapreturn Rcpp::List::create(

Rcpp::Named("front", x.front()),Rcpp::Named("back", x.back())

);’

fun <- cxxfunction(signature(inp = "list"),code, plugin = "Rcpp")

input <- list(x = seq(1, 10, by = 0.5))fun(input)

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Outline

2 Extending Rcpp via as and wrapIntroductionExtending wrapExtending asExample

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Extending wrap: Intrusively

We can declare a new conversion to SEXP operator for classFoo in a header Foo.h before the header Rcpp.h is included.

#include <RcppCommon.h>

class Foo {public:

Foo();

// this operator enables implicit Rcpp::wrapoperator SEXP();

}

#include <Rcpp.h>

The definition can follow in a regular Foo.cpp file.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Extending wrap: Non-Intrusively

If we cannot modify the class of the code for which we need awrapper, but still want automatic conversion we can use atemplate specialization for wrap:

#include <RcppCommon.h>

// third party library that declares class Bar#include <foobar.h>

// declaring the specializationnamespace Rcpp {

template <> SEXP wrap( const Bar& );}

// this must appear after the specialization,// otherwise the specialization will not be seen by Rcpp types#include <Rcpp.h>

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Extending wrap: Partial specialization

We can also declare a partial specialization as the compiler willpick the appropriate overloading:#include <RcppCommon.h>

// third party library that declares template class Bling<T>#include <foobar.h>

// declaring the partial specializationnamespace Rcpp {

namespace traits {

template <typename T> SEXP wrap( const Bling<T>& ) ;

}}

// this must appear after the specialization,// otherwise the specialization will not be seen by Rcpp types#include <Rcpp.h>

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Outline

2 Extending Rcpp via as and wrapIntroductionExtending wrapExtending asExample

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Extending as: Intrusively

Just like for wrap, we can provide an intrusive conversion bydeclaring a new constructor from SEXP for class Foo before theheader Rcpp.h is included:

#include <RcppCommon.h>

class Foo{public:

Foo() ;

// this constructor enables implicit Rcpp::asFoo(SEXP) ;

}

#include <Rcpp.h>

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Extending as: Non-Intrusively

We can also use a full specialization of as in a non-intrusivemanner:

#include <RcppCommon.h>

// third party library that declares class Bar#include <foobar.h>

// declaring the specializationnamespace Rcpp {

template <> Bar as( SEXP ) throw(not_compatible) ;}

// this must appear after the specialization,// otherwise the specialization will not be seen by Rcpp types#include <Rcpp.h>

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Extending as: Partial specialization

Rcpp::as does not allow partial specialization. We canspecialize Rcpp::traits::Exporter.Partial specialization of class templayes is allowed; we can do#include <RcppCommon.h>// third party library that declares template class Bling<T>#include <foobar.h>

// declaring the partial specializationnamespace Rcpp {

namespace traits {template <typename T> class Exporter< Bling<T> >;

}}// this must appear after the specialization,// otherwise the specialization will not be seen by Rcpp types#include <Rcpp.h>

Requirements for the Exporter< Bling<T> > class are thatit should have a constructor taking a SEXP, and it should have amethods called get that returns a Bling<T> instance.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

Outline

3 Using Rcpp in your packageOverviewCallC++ filesR fileDESCRIPTION and NAMESPACEMakevars and Makevars.win

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

The RcppBDT package wraps Boost Date_TimeA simple use case of Rcpp modules

Here, as and wrap simply convert between a Daterepresentation from R and one from Boost:

// define template specialisations for as and wrapnamespace Rcpp {

template <> boost::gregorian::date as( SEXP dtsexp ) {Rcpp::Date dt(dtsexp);return boost::gregorian::date(dt.getYear(), dt.getMonth(), dt.getDay());

}

template <> SEXP wrap(const boost::gregorian::date &d) {boost::gregorian::date::ymd_type ymd = d.year_month_day(); // to y/m/d structreturn Rcpp::wrap(Rcpp::Date( ymd.year, ymd.month, ymd.day ));

}}

The header file provides both the declaration and theimplementation: a simple conversion from one representationto another.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Intro Extending wrap Extending as Example

The RcppBDT package wraps Boost Date_TimeExample usage of as and wrap

Two converters provide a simple usage example:

// thanks to wrap() template aboveRcpp::Date date_toDate(boost::gregorian::date *d) {

return Rcpp::wrap(*d);}

// thanks to asvoid date_fromDate(boost::gregorian::date *d, SEXP dt) {

*d = Rcpp::as<boost::gregorian::date>(dt);}

There are more examples in the (short) package sources.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Outline

3 Using Rcpp in your packageOverviewCallC++ filesR fileDESCRIPTION and NAMESPACEMakevars and Makevars.win

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Creating a package with Rcpp

R provides a very useful helper function to create packages:package.skeleton().

We have wrapped / extended this function toRcpp.package.skeleton() to create a framework for auser package.

The next few slides will show its usage.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Outline

3 Using Rcpp in your packageOverviewCallC++ filesR fileDESCRIPTION and NAMESPACEMakevars and Makevars.win

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Calling Rcpp.package.skeleton()

R> Rcpp.package.skeleton( "mypackage" )Creating directories ...Creating DESCRIPTION ...Creating NAMESPACE ...Creating Read-and-delete-me ...Saving functions and data ...Making help files ...Done.Further steps are described in ’./mypackage/Read-and-delete-me’.

Adding Rcpp settings>> added Depends: Rcpp>> added LinkingTo: Rcpp>> added useDynLib directive to NAMESPACE>> added Makevars file with Rcpp settings>> added Makevars.win file with Rcpp settings>> added example header file using Rcpp classes>> added example src file using Rcpp classes>> added example R file calling the C++ example>> added Rd file for rcpp_hello_world

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Rcpp.package.skeleton creates a file tree

We will discuss the individualfiles in the next few slides.

Note that the next version ofRcpp will include two more.cpp files.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Outline

3 Using Rcpp in your packageOverviewCallC++ filesR fileDESCRIPTION and NAMESPACEMakevars and Makevars.win

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

The C++ header file

#ifndef _mypackage_RCPP_HELLO_WORLD_H#define _mypackage_RCPP_HELLO_WORLD_H

#include <Rcpp.h>

/** note : RcppExport is an alias to ‘extern "C"‘ defined by Rcpp.** It gives C calling convention to the rcpp_hello_world function so that* it can be called from .Call in R. Otherwise, the C++ compiler mangles the* name of the function and .Call can’t find it.** It is only useful to use RcppExport when the function is intended to be called* by .Call. See http://thread.gmane.org/gmane.comp.lang.r.rcpp/649/focus=672* on Rcpp-devel for a misuse of RcppExport*/RcppExport SEXP rcpp_hello_world() ;

#endif

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

The C++ source file

#include "rcpp_hello_world.h"

SEXP rcpp_hello_world(){using namespace Rcpp ;

CharacterVector x = CharacterVector::create( "foo", "bar" ) ;NumericVector y = NumericVector::create( 0.0, 1.0 ) ;List z = List::create( x, y ) ;

return z ;}

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Outline

3 Using Rcpp in your packageOverviewCallC++ filesR fileDESCRIPTION and NAMESPACEMakevars and Makevars.win

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

The R file

The R file makes one call to the one C++ function:

rcpp_hello_world <- function(){.Call( "rcpp_hello_world",

PACKAGE = "mypackage" )}

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Outline

3 Using Rcpp in your packageOverviewCallC++ filesR fileDESCRIPTION and NAMESPACEMakevars and Makevars.win

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

The DESCRIPTION file

This declares the dependency of your package on Rcpp.Package: mypackageType: PackageTitle: What the package does (short line)Version: 1.0Date: 2011-04-19Author: Who wrote itMaintainer: Who to complain to <[email protected]>Description: More about what it does (maybe more than one line)License: What Licence is it under ?LazyLoad: yesDepends: Rcpp (>= 0.9.4)LinkingTo: Rcpp

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

The NAMESPACE file

Here we use a regular expression to export all symbols.

useDynLib(mypackage)exportPattern("^[[:alpha:]]+")

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Outline

3 Using Rcpp in your packageOverviewCallC++ filesR fileDESCRIPTION and NAMESPACEMakevars and Makevars.win

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

The standard Makevars file

## Use the R_HOME indirection to support installations of multiple R versionPKG_LIBS = ‘$(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()"‘

## As an alternative, one can also add this code in a file ’configure’#### PKG_LIBS=‘${R_HOME}/bin/Rscript -e "Rcpp:::LdFlags()"‘#### sed -e "s|@PKG_LIBS@|${PKG_LIBS}|" \## src/Makevars.in > src/Makevars#### which together with the following file ’src/Makevars.in’#### PKG_LIBS = @PKG_LIBS@#### can be used to create src/Makevars dynamically. This scheme is more## powerful and can be expanded to also check for and link with other## libraries. It should be complemented by a file ’cleanup’#### rm src/Makevars#### which removes the autogenerated file src/Makevars.#### Of course, autoconf can also be used to write configure files. This is## done by a number of packages, but recommended only for more advanced users## comfortable with autoconf and its related tools.

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

The Windows Makevars.win file

On Windows we have to also reflect 32- and 64-bit builds in thecall to Rscript:

## Use the R_HOME indirection to support installations of multiple R versionPKG_LIBS = \

$(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" \-e "Rcpp:::LdFlags()")

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Classes Extending package Overview Call C++ files R file Other Makevars

Installation and Usage

edd@max:/tmp$ R CMD INSTALL mypackage

* installing to library ’/usr/local/lib/R/site-library’

* installing *source* package ’mypackage’ ...

** libsg++ -I/usr/share/R/include [....]g++ -shared -o mypackage.so [....]installing to /usr/local/lib/R/site-library/mypackage/libs

** R

** preparing package for lazy loading

** help

*** installing help indices

** building package indices ...

** testing if installed package can be loaded

* DONE (mypackage)edd@max:/tmp$ Rscript -e ’library(mypackage); rcpp_hello_world()’Loading required package: RcppLoading required package: methods[[1]][1] "foo" "bar"

[[2]][1] 0 1

edd@max:/tmp$

Dirk Eddelbuettel Rcpp Tutorial — Part II: Rcpp Details

Rcpp sugar Rcpp Modules Rcpp Classes

Rcpp TutorialPart III: Advanced Rcpp

Dr. Dirk [email protected]

[email protected]

useR! 2012Vanderbilt University

June 12, 2012

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Outline

1 Syntactic sugar

2 Rcpp Modules

3 Rcpp Classes

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Motivating Sugar

Recall the earlier example of a simple (albeit contrived for thepurposes of this discussion) R vector expression:

ifelse(x < y, x*x, -(y*y))

which for a given vector x will execute a simple transformation.

We saw a basic C implementation. How would we write it inC++ ?

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Motivating sugarexamples/part3/sugarEx1.cpp

Maybe like this.SEXP foo(SEXP xx, SEXP yy) {

int n = x.size();NumericVector res1( n );double x_ = 0.0, y_ = 0.0;for (int i=0; i<n; i++) {

x_ = x[i];y_ = y[i];if (R_IsNA(x_) || R_IsNA(y_)) {res1[i] = NA_REAL;

} else if (x_ < y_) {res1[i] = x_ * x_;

} else {res1[i] = -(y_ * y_);

}}return(x);

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Motivating sugarexamples/part3/sugarEx2.cpp

But with sugar we can simply write it as

SEXP foo( SEXP xx, SEXP yy) {NumericVector x(xx), y(yy) ;return ifelse( x < y, x*x, -(y*y) ) ;

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Sugar: Another exampleexamples/part3/sugarEx3.cpp

Sugar also gives us things like sapply on C++ vectors:

double square( double x){return x*x ;

}

SEXP foo( SEXP xx ){NumericVector x(xx) ;return sapply( x, square ) ;

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Sugar: Overview of Contents

logical operators <, >, <=, >=, ==, !=arithmetic operators +, -, *, /functions on vectors abs, all, any, ceiling, cumsum, diag,

diff, exp, head, ifelse, is_na, lapply,mean, pmin, pmax, pow, rep, rep_each,rep_len, rev, sapply, seq_along, seq_len,sd, sign, sum, tail, var,

functions on matrices outer, col, row, lower_tri,upper_tri, diag

statistical functions (dpqr) rnorm, dpois, qlogis, etc ...

More information in the Rcpp-sugar vignette.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Binary arithmetic operators

Sugar defines the usual binary arithmetic operators : +, -, *, /.// two numeric vectors of the same sizeNumericVector x ;NumericVector y ;

// expressions involving two vectorsNumericVector res = x + y ;NumericVector res = x - y ;NumericVector res = x * y ;NumericVector res = x / y ;

// one vector, one single valueNumericVector res = x + 2.0 ;NumericVector res = 2.0 - x;NumericVector res = y * 2.0 ;NumericVector res = 2.0 / y;

// two expressionsNumericVector res = x * y + y / 2.0 ;NumericVector res = x * ( y - 2.0 ) ;NumericVector res = x / ( y * y ) ;

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Binary logical operators// two integer vectors of the same sizeNumericVector x ;NumericVector y ;

// expressions involving two vectorsLogicalVector res = x < y ;LogicalVector res = x > y ;LogicalVector res = x <= y ;LogicalVector res = x >= y ;LogicalVector res = x == y ;LogicalVector res = x != y ;

// one vector, one single valueLogicalVector res = x < 2 ;LogicalVector res = 2 > x;LogicalVector res = y <= 2 ;LogicalVector res = 2 != y;

// two expressionsLogicalVector res = ( x + y ) < ( x*x ) ;LogicalVector res = ( x + y ) >= ( x*x ) ;LogicalVector res = ( x + y ) == ( x*x ) ;

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Unary operators

// a numeric vectorNumericVector x ;

// negate xNumericVector res = -x ;

// use it as part of a numerical expressionNumericVector res = -x * ( x + 2.0 ) ;

// two integer vectors of the same sizeNumericVector y ;NumericVector z ;

// negate the logical expression "y < z"LogicalVector res = ! ( y < z );

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Functions producing a single logical result

IntegerVector x = seq_len( 1000 ) ;all( x*x < 3 ) ;

any( x*x < 3 ) ;

// wrong: will generate a compile errorbool res = any( x < y) ) ;

// okbool res = is_true( any( x < y ) )bool res = is_false( any( x < y ) )bool res = is_na( any( x < y ) )

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Functions producing sugar expressionsIntegerVector x = IntegerVector::create( 0, 1, NA_INTEGER, 3 ) ;

is_na( x )all( is_na( x ) )any( ! is_na( x ) )

seq_along( x )seq_along( x * x * x * x * x * x * x )

IntegerVector x = seq_len( 10 ) ;

pmin( x, x*x );pmin( x*x, 2 );

IntegerVector x, y;

ifelse( x < y, x, (x+y)*y );ifelse( x > y, x, 2 );

sign( xx );sign( xx * xx );

diff( xx );

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Mathematical functions

IntegerVector x;

abs( x )exp( x )log( x )log10( x )floor( x )ceil( x )sqrt( x )pow(x, z) # x to the power of z

plus the regular trigonometrics functions and more.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Statistical function d/q/p/r

x1 = dnorm(y1, 0, 1); // density of y1 at m=0, sd=1x2 = pnorm(y2, 0, 1); // distribution function of y2x3 = qnorm(y3, 0, 1); // quantiles of y3x4 = rnorm(n, 0, 1); // ’n’ RNG draws of N(0, 1)

For beta, binom, caucht, exp, f, gamma, geom, hyper, lnorm,logis, nbeta, nbinom, nbinom_mu, nchisq, nf, norm, nt, pois, t,unif and weibull.

Use something like RNGScope scope; to set/reset the RNGs.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Sugar: benchmarks

expression sugar R R / sugar

any(x*y<0) 0.000451 5.17 11450

ifelse(x<y,x*x,-(y*y)) 1.378 13.15 9.54ifelse(x<y,x*x,-(y*y))

(?) 1.254 13.03 10.39

sapply(x,square) 0.220 113.38 515.24

Source: examples/SugarPerformance/ using R 2.13.0, Rcpp 0.9.4, g++-4.5, Linux 2.6.32, i7 cpu.

? : version includes optimization related to the absence of missing values

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Sugar: benchmarks

Benchmarks of the convolution example from Writing RExtensions.

Implementation Time in Relativemillisec to R API

R API (as benchmark) 234Rcpp sugar 158 0.68NumericVector::iterator 236 1.01NumericVector::operator[] 305 1.30R API naively 2199 9.40

Table: Convolution of x and y (200 values), repeated 5000 times.

Source: examples/ConvolveBenchmarks/ using R 2.13.0, Rcpp 0.9.4, g++-4.5, Linux 2.6.32, i7 cpu.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Sugar: Final Exampleexamples/part3/sugarExample.R

Consider a simple R function of a vector:

foo <- function(x) {

## sum of## -- squares of negatives## -- exponentials of positivess <- sum(ifelse( x < 0, x*x, exp(x) ))

return(s)}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Sugar: Final Exampleexamples/part3/sugarExample.R

Here is one C++ solution:

bar <- cxxfunction(signature(xs="numeric"),plugin="Rcpp", body=’

NumericVector x(xs);

double s = sum( ifelse( x < 0, x*x, exp(x) ));

return wrap(s);’)

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Motivation Contents Operators Functions Performance

Sugar: Final ExampleBenchmark from examples/part3/sugarExample.R

R> library(compiler)R> cfoo <- cmpfun(foo)R> library(rbenchmark)R> x <- rnorm(1e5)R> benchmark(foo(x), cfoo(x), bar(x),+ columns=c("test", "elapsed", "relative",+ "user.self", "sys.self"),+ order="relative", replications=10)

test elapsed relative user.self sys.self3 bar(x) 0.033 1.0000 0.03 01 foo(x) 0.441 13.3636 0.45 02 cfoo(x) 0.463 14.0303 0.46 0R>

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Outline

1 Syntactic sugar

2 Rcpp Modules

3 Rcpp Classes

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Rcpp Modules - Motivation

The Rcpp API makes it easier to write and maintain C++extension for R.

But we can do better still:

Even more direct interfaces between C++ and RAutomatic handling / unwrapping of argumentsSupport exposing C++ functions to RAlso support exposing C++ classes to R

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Standing on the shoulders of Boost.Python

Boost.Python is a C++ library which enables seamlessinteroperability between C++ and the Python programminglanguage.

Rcpp Modules borrows from Boost.Python to implementsimilar interoperability between R and C++.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Rcpp Modules

C++ functions and classes:

double square( double x ){return x*x;

}

class Foo {public:Foo(double x_) : x(x_) {}

double bar( double z){return pow( x - z, 2.0);

}

private:double x;

};

This can be used in R:

> square( 2.0 )[1] 4

> x <- new( Foo, 10 )> x$bar( 2.0 )[1] 64

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ functions

Consider the simple function :

double norm( double x, double y ){return sqrt( x*x + y*y ) ;

}

Exercise : try to expose this function to R with what we havelearned this morning. We want an R function that does this:

> norm( 2, 3 )[1] 3.605551

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ functions

C++ side:

#include <Rcpp.h>double norm( double x, double y ){

return sqrt( x*x + y*y) ;}

SEXP norm_wrapper(SEXP x_, SEXP y_) {[...]

}

Compile with R CMD SHLIB:

$ R CMD SHLIB foo.cpp

R side:

dyn.load( "foo.so" )norm <- function(x, y){

.Call( [...] , x, y )}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ functionsWith inline

inc <- ’double norm( double x, double y ){

return sqrt( x*x + y*y) ;}’src <- ’

// convert the inputsdouble x = as<double>(x_), y = as<double>(y_);

// call the function and store the resultdouble res = norm( x, y ) ;

// convert the resultreturn wrap(y) ;

’norm <- cxxfunction(signature(x_ = "numeric",

y_ = "numeric" ),body = src, includes = inc,plugin = "Rcpp" )

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ functions (cont.)

So exposing a C++ function to R is straightforward, yet alsosomewhat tedious:

Convert the inputs (from SEXP) to the appropriate typesCall the function and store the resultConvert the result to a SEXP

Rcpp Modules use Template Meta Programming (TMP) toreplace these steps by a single step:

Declare which function to expose

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ functions with modulesWithin a package

C++ side:#include <Rcpp.h>

double norm( double x, double y ){return sqrt( x*x + y*y) ;

}RCPP_MODULE(foo){

function( "norm", &norm ) ;}

R side:.onLoad <- function(libname, pkgname){

loadRcppModules()}

(Other details related to module loading to take care of. We willcover them later.)

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ functions with modulesUsing inline

fx <- cxxfunction(, "", includes = ’double norm( double x, double y ){return sqrt( x*x + y*y) ;

}RCPP_MODULE(foo){

function( "norm", &norm ) ;}

’, plugin = "Rcpp" )

foo <- Module( "foo", getDynLib(fx) )

norm <- foo$norm

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ functionsDocumentation

.function can take an additional argument to document theexposed function:double norm( double x, double y ){

return sqrt( x*x + y*y) ;}RCPP_MODULE(foo){

function("norm", &norm,"Some documentation about the function");

}

which can be displayed from the R prompt:R> show( mod$norm )internal C++ function <0x1c21220>docstring : Some documentation about the functionsignature : double norm(double, double)

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ functionsFormal arguments

Modules also let you supply formal arguments for moreflexibility:using namespace Rcpp;double norm( double x, double y ) {

return sqrt( x*x + y*y );}

RCPP_MODULE(mod_formals2) {function( "norm", &norm,

List::create( _["x"], _["y"] = 0.0 ),"Provides a simple vector norm");

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ functionsFormal arguments

Rcpp modules supports different types of arguments:

Argument without default value : _["x"]Argument with default value : _["y"] = 2

Ellipsis (...) : _["..."]

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classesMotivation

Motivation: We want to manipulate C++ objects:

Create instancesRetrieve/Set data membersCall methods

External pointers are useful for that, and Rcpp modules wrapsthem in a nice to use abstration.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes

A simple C++ class:class Uniform {public:

// constructorUniform(double min_, double max_) :

min(min_), max(max_) {}

// methodNumericVector draw(int n) const {

RNGScope scope;return runif( n, min, max );

}

// fieldsdouble min, max;

};

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes

Modules can expose the Uniform class to allow this syntax:> u <- new( Uniform, 0, 10 )> u$draw( 10L )[1] 3.00874606 7.00303770 6.17387340 0.06449014 7.40344856[6] 6.48737922 1.73829428 7.53417005 0.38615597 6.66649310> u$min[1] 0> u$max[1] 10> u$min <- 5> u$draw(10)[1] 7.02818458 8.19557570 5.42092100 6.02311031 8.18770124[6] 6.18817312 8.60004068 6.60542979 5.41539068 9.96131797

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes

Since C++ does not have reflection capabilities, modules needto declare what to expose:

ConstructorsFields or propertiesMethodsFinalizers

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classesA simple example

class Uniform {public:

Uniform(double min_, double max_) : min(min_), max(max_) {}NumericVector draw(int n) const {

RNGScope scope;return runif( n, min, max );

}double min, max;

};

RCPP_MODULE(random){class_<Uniform>( "Uniform").constructor<double,double>()

.field( "min", &Uniform::min )

.field( "max", &Uniform::max )

.method( "draw", &Uniform::draw );

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes... Exposing constructors

class Uniform {public:

Uniform(double min_, double max_) : min(min_), max(max_) {}NumericVector draw(int n) const {

RNGScope scope;return runif( n, min, max );

}double min, max;

};

RCPP_MODULE(random){class_<Uniform>( "Uniform").constructor<double,double>()

.field( "min", &Uniform::min )

.field( "max", &Uniform::max )

.method( "draw", &Uniform::draw );

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes... Exposing fields

class Uniform {public:

Uniform(double min_, double max_) : min(min_), max(max_) {}NumericVector draw(int n) const {

RNGScope scope;return runif( n, min, max );

}double min, max;

};

RCPP_MODULE(random){class_<Uniform>( "Uniform").constructor<double,double>()

.field( "min", &Uniform::min )

.field( "max", &Uniform::max )

.method( "draw", &Uniform::draw );

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes... Exposing methods

class Uniform {public:

Uniform(double min_, double max_) : min(min_), max(max_) {}NumericVector draw(int n) const {

RNGScope scope;return runif( n, min, max );

}double min, max;

};

RCPP_MODULE(random){class_<Uniform>( "Uniform").constructor<double,double>()

.field( "min", &Uniform::min )

.field( "max", &Uniform::max )

.method( "draw", &Uniform::draw );

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes... Constructors

The .constructor method of class_ can expose publicconstructors taking between 0 and 7 arguments.

The argument types are specified as template parameters ofthe .constructor methods.

It is possible to expose several constructors that take the samenumber of arguments, but this require the developper toimplement dispatch to choose the appropriate constructor.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes... Fields

Public data fields are exposed with the .field memberfunction:.field( "x", &Uniform::x )

If you do not wish the R side to have write access to a field, youcan use the .field_readonly field:.field_readonly( "x", &Uniform::x )

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes... Properties

Properties let the developper associate getters (and optionallysetters) instead of retrieving the data directly. This can beuseful for:

Private or protected fieldsTo keep track of field accessTo add operations when a field is retrieved or setTo create a pseudo field that is not directly related to a datamember of the class

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes... Properties

Properties are declared with one of the .property overloads:.property( "z",

&Foo::get_z,&Foo::set_z,"Documentation" )

This containsthe R side name of the property (required)address of the getter (required)address of the setter (optional)documentation for the property (optional)

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes... Properties, getters

Getters can be:class Foo{public:

double get(){ ... }...

} ;

double outside_get( Foo* foo ){ ... }

Public member functions of the target class that take noargument and return somethingFree functions that take a pointer to the target class asunique argument and returns something

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classes... Properties, setters

Setters can be:class Foo{public:

void set(double x){ ... }...

} ;

void outside_set( Foo* foo , double x){ ... }

Public member functions that take exactly one argument(which must match with the type used in the getter)Free function that takes exactly two arguments: a pointerto the target class, and another variable (which must matchthe type used in the getter).

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exposing C++ classesFields and properties example

class Foo{public:

double x, y ;double get_z(){ return z; }void set_z( double new_z ){ z = new_z ; }// ...

private:double z ;

};double get_w(Foo* foo){ ... }void set_w(Foo* foo, double w ){ ... }

RCPP_MODULE(bla){class_<Foo>("Foo")// ....field( "x", &Foo::x ).field_readonly( "y", &Foo::y ).property( "z", &Foo::get_z, Foo::set_z ).property( "w", &get_w, &set_w );

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

... Methods

The .method member function of class_ is used to exposemethods, which can be:

A public member function of the target class, const or nonconst, that takes between 0 and 65 parameters andreturns either void or somethingA free function that takes a pointer to the target class,followed by between 0 and 65 parameters, and returnseither void or something

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

... Methods, examples

class Foo{public:

...void bla() ;double bar( int x, std::string y ) ;

} ;double yada(Foo* foo) { ... }

RCPP_MODULE(mod){class_<Foo>....method( "bla" , &Foo::bla ).method( "bar" , &Foo::bar ).method( "yada", &yada );

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

... Finalizers

When the R reference object that wraps the internal C++ objectgoes out of scope, it becomes candidate for GC.

When it is GC’ed, the destructor of the target class is called.

Finalizers allow the developper to add behavior right before thedestructor is called (free resources, etc ...)

Finalizers are associated to exposed classes with theclass_::.finalizer method. A finalizer is a free functionthat takes a pointer to the target class as unique argument andreturns void.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exercize : expose this class

class Normal{public:

// 3 constructorsNormal() : mean(0.0), sd(1.0){}Normal(double mean_) : mean(mean_), sd(1.0){}Normal(double mean_, double sd_) :mean(mean_), sd(sd_){}

// one methodNumericVector draw(int n){RNGScope scope ;return rnorm( n, mean, sd ) ;

}

// two fields (declare them read-only)double mean, sd ;

} ;

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Modules and packages

The best way to use Rcpp modules is to embed them in an Rpackage.

The Rcpp.package.skeleton (and its module argument)creates a package skeleton that has an Rcpp module.

> Rcpp.package.skeleton("mypackage",+ module = TRUE )

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Modules and packages> Rcpp.package.skeleton( "mypackage", module=TRUE )Creating directories ...Creating DESCRIPTION ...Creating NAMESPACE ...Creating Read-and-delete-me ...Saving functions and data ...Making help files ...Done.Further steps are described in ’./mypackage/Read-and-delete-me’.

Adding Rcpp settings>> added RcppModules: yada>> added Depends: Rcpp>> added LinkingTo: Rcpp>> added useDynLib directive to NAMESPACE>> added Makevars file with Rcpp settings>> added Makevars.win file with Rcpp settings>> added example header file using Rcpp classes>> added example src file using Rcpp classes>> added example R file calling the C++ example>> added Rd file for rcpp_hello_world>> copied the example module

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Calling Rcpp.package.skeleton

We will discuss the individualfiles in the next few slides.

Also note that the nextrelease will contain two morecpp files.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

rcpp_module.cpp#include <Rcpp.h>

[...]int bar( int x){

return x*2 ;}double foo( int x, double y){

return x * y ;}[...]

class World {public:

World() : msg("hello"){}void set(std::string msg) { this->msg = msg; }std::string greet() { return msg; }

private:std::string msg;

};

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

rcpp_module.cpp

RCPP_MODULE(yada){using namespace Rcpp ;

[...]

function( "bar", &bar,List::create( _["x"] = 0.0 ),"documentation for bar " ) ;

function( "foo" , &foo ,List::create( _["x"] = 1, _["y"] = 1.0 ),"documentation for foo " ) ;

class_<World>( "World" ).constructor().method( "greet", &World::greet , "get the message" ).method( "set", &World::set , "set the message" )

;}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Modules and packages: DESCRIPTION

Package: mypackageType: PackageTitle: What the package does (short line)Version: 1.0Date: 2011-08-15Author: Who wrote itMaintainer: Who to complain to <[email protected]>Description: More about what it does (maybe more than one line)License: What Licence is it under ?LazyLoad: yesDepends: methods, Rcpp (>= 0.9.6)LinkingTo: RcppRcppModules: yada

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Modules and packages: zzz.R

The .onLoad() function (often in zzz.R file) must contain acall to the loadRcppModules function.

For the next R version, we can switch to evalqOnLoad().## For R 2.15.0 we still need require(), but note the R CMD check issue.onLoad <- function(libname, pkgname){

require("methods") ## needed, but upsets R CMD checkloadRcppModules()

}

## For R 2.15.1 and later this will work#evalqOnLoad({# loadModule("NumEx", TRUE)# loadModule("yada", TRUE)# loadModule("stdVector", TRUE)#})

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Modules and packages: NAMESPACE

The NAMESPACE files loads the dyanmic library of thepackages, imports from Rcpp and exports all local symbols ofthe package (using regular expression).

useDynLib(mypackage)exportPattern("^[[:alpha:]]+")import( Rcpp )

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Modules and packages: Using the package> require( mypackage )> foointernal C++ function <0x100612350>

docstring : documentation for foosignature : double foo(int, double)

> foo( 2, 3 )[1] 6> WorldC++ class ’World’ <0x10060edc0>Constructors:

World()

Fields: No public fields exposed by this class

Methods:std::string greet()

docstring : get the messagevoid set(std::string)

docstring : set the message> w <- new( World )> w$set( "bla bla" )> w$greet()[1] "bla bla"

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

stdVector.cpp (in Rcpp’s skeleton and unittest)

#include <Rcpp.h> // need to include the main Rcpp header file only

typedef std::vector<double> vec; // convenience typedef

void vec_assign( vec* obj, Rcpp::NumericVector data) { // helpersobj->assign( data.begin(), data.end() ) ;

}void vec_insert( vec* obj, int position, Rcpp::NumericVector data) {

vec::iterator it = obj->begin() + position;obj->insert( it, data.begin(), data.end() );

}

Rcpp::NumericVector vec_asR( vec* obj) {return Rcpp::wrap( *obj );

}

void vec_set( vec* obj, int i, double value) {obj->at( i ) = value;

}

void vec_resize( vec* obj, int n) { obj->resize( n ); }void vec_push_back( vec* obj, double x ) { obj->push_back( x ); }

// Wrappers for member functions that return a reference -- required on Solarisdouble vec_back(vec *obj){ return obj->back() ; }double vec_front(vec *obj){ return obj->front() ; }double vec_at(vec *obj, int i){ return obj->at(i) ; }

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

stdVector.cpp cont.RCPP_MODULE(stdVector){

using namespace Rcpp ;// we expose the class std::vector<double> as "vec" on the R sideclass_<vec>("vec")// exposing the default constructor.constructor()// exposing member functions -- taken directly from std::vector<double>.method( "size", &vec::size).method( "max_size", &vec::max_size).method( "capacity", &vec::capacity).method( "empty", &vec::empty).method( "reserve", &vec::reserve).method( "pop_back", &vec::pop_back ).method( "clear", &vec::clear )// specifically exposing const member functions defined above.method( "back", &vec_back ).method( "front", &vec_front ).method( "at", &vec_at )// exposing free functions taking a std::vector<double>*// as their first argument.method( "assign", &vec_assign ).method( "insert", &vec_insert ).method( "as.vector",&vec_asR ).method( "push_back",&vec_push_back ).method( "resize", &vec_resize)// special methods for indexing.method( "[[", &vec_at ).method( "[[<-", &vec_set );

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

stdVector.cpp cont.Usage from R

v <- new(vec) # stdVector module

data <- 1:10v$assign(data)

v[[3]] <- v[[3]] + 1data[[4]] <- data[[4]] +1

checkEquals( v$as.vector(), data )

v$size()v$capacity()

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

planar/src/multilayer.cpp

#include <RcppArmadillo.h>#include <iostream>

using namespace Rcpp ;using namespace RcppArmadillo ;using namespace arma ;using namespace std;

Rcpp::List multilayer(const arma::colvec& k0, \const arma::cx_mat& kx, \const arma::cx_mat& epsilon, \const arma::colvec& thickness, \const int& polarisation) {

[...]Rcpp::List recursive_fresnel(const arma::colvec& k0, \

const arma::cx_mat& kx, \const arma::cx_mat& epsilon, \const arma::colvec& thickness, \const int& polarisation) {

[...]

RCPP_MODULE(planar){using namespace Rcpp;

function( "multilayer", &multilayer, \"Calculates reflection and transmission coefficients of a multilayer stack" );

function( "recursive_fresnel", &recursive_fresnel, \"Calculates the reflection coefficient of a multilayer stack" );

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

cda/src/{cda,utils}.cpp

#include "utils.h"#include "cda.h"#include <RcppArmadillo.h>#include <iostream>

using namespace Rcpp;using namespace RcppArmadillo;using namespace std;

arma::mat euler(const double phi, const double theta, const double psi) {[...]arma::cx_mat interaction_matrix(const arma::mat& R, const double kn,

const arma::cx_mat& invAlpha,const arma::mat& Euler, const int full) {

double extinction(const double kn, const arma::cx_colvec& P,const arma::cx_colvec& Eincident) {

[...]double absorption(const double kn, const arma::cx_colvec& P,

const arma::cx_mat& invpolar) {[...]

RCPP_MODULE(cda){using namespace Rcpp ;

function( "euler", &euler, "Constructs a 3x3 Euler rotation matrix" ) ;function( "extinction", &extinction, "Calculates the extinction cross-section" ) ;function( "absorption", &absorption, "Calculates the absorption cross-section" ) ;function( "interaction_matrix", &interaction_matrix,

"Constructs the coupled-dipole interaction matrix" ) ;}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

GUTS/src/GUTS_rpp_module.cpp

#include "GUTS.h"#include <Rcpp.h>

using namespace Rcpp;

RCPP_MODULE(modguts){class_<GUTS>( "GUTS" )

.constructor()

.method( "setConcentrations", &GUTS::setConcentrations,"Set time series vector of concentrations." )

.method( "setSurvivors", &GUTS::setSurvivors,"Set time series vector of survivors." )

[...]

.method( "setSample", &GUTS::setSample, "Set ordered sample vector." )

.method( "calcLoglikelihood", &GUTS::calcLoglikelihood,"Returns calculated log. of likelihood from complete + valid object." )

.property( "C", &GUTS::getC, "Vector of concentrations." )

.property( "Ct", &GUTS::getCt, "Time vector of concentrations." )[...];

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

RcppBDT/src/RcppBDT.cppRCPP_MODULE(bdt) {

using namespace boost::gregorian;using namespace Rcpp;

// exposing a class (boost::gregorian::)date as "date" on the R sideclass_<date>("date")

// constructors.constructor("default constructor").constructor<int, int, int>("constructor from year, month, day")

.method("setFromLocalClock", &date_localDay, "create a date from local clock")

.method("setFromUTC", &date_utcDay, "create a date from current universal clock")[...].method("getYear", &date_year, "returns the year").method("getMonth", &date_month, "returns the month").method("getDay", &date_day, "returns the day").method("getDayOfYear", &date_dayofyear, "returns the day of the year")[...].method("getDate", &date_toDate, "returns an R Date object").method("fromDate", &date_fromDate, "sets date from an R Date object")[...].const_method("getWeekNumber", &date::week_number, "returns number of week").const_method("getModJulian", &date::modjulian_day, "returns the mod. Julian day").const_method("getJulian", &date::julian_day, "returns the Julian day")[...].method("getNthDayOfWeek", &Date_nthDayOfWeek,

"return nth week’s given day-of-week in given month and year")[...];

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exercise

Create a package with a module : start by usingRcpp.package.skeleton

Expose two C++ functionsExpose a C++ class

double fun1( NumericVector x){return sum(head(x,-1) - tail(x,-1)

) ;}

double fun2( NumericVector x ){return mean(x) / sd(x) ;

}

class Normal {public:Normal(

double mean_, double sd_) ;NumericVector draw( int n ) ;int get_ndraws() ;

private:double mean, sd ;int ndraws ;

} ;

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exerciseclass Normal; // forward declarationdouble sumdiff(Normal *obj, NumericVector x) {

return sum(head(x,-1) - tail(x,-1));}double zscore(Normal *obj, NumericVector x ) {

return mean(x) / sd(x) ;}class Normal {public:

Normal(double mean_, double sd_) : mean(mean_), sd(sd_), ndraws(0) {};NumericVector draw( int n ) {

ndraws += n;RNGScope scope;return rnorm(n, mean, sd);

}int get_ndraws() {

return ndraws;}

private:double mean, sd ;int ndraws ;

} ;RCPP_MODULE(newmod) {

class_<Normal>("Normal").constructor<double, double>().method("draw", &Normal::draw).method("get_ndraws", &Normal::get_ndraws).method("sumdiff", &sumdiff).method("zscore", &zscore);

}

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Intro Classes Packages STL CRAN Exercise

Exercise

fx <- cxxfunction(signature(), plugin="Rcpp", include=inc)newmod <- Module("newmod", getDynLib(fx))

nn <- new(newmod$Normal, 10, 10)set.seed(42)z <- nn$draw(4)nn$sumdiff(z)nn$zscore(z)

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Overview Example

Outline

1 Syntactic sugar

2 Rcpp Modules

3 Rcpp Classes

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Overview Example

Overview

Recently, John Chambers committed some code which will bein the next Rcpp release. This builds on Rcpp Modules, andallows the R side to modify C++ classes.

This is documented in help(setRcppClass) as well as inone test package to to support the unit tests.

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

Rcpp sugar Rcpp Modules Rcpp Classes Overview Example

ExamplesetRcppClass("World", module = "yada", fields = list(more = "character"),

methods = list(test = function(what) message("Testing: ", what, "; ", more)),saveAs = "genWorld")

setRcppClass("stdNumeric", "vec", "stdVector")evalqOnLoad({ # some methods that use C++ methods

stdNumeric$methods(getEl = function(i) {

i <- as.integer(i)if(i < 1 || i > size())

NA_real_else

at(i-1L)},setEl = function(i, value) {

value <- as.numeric(value)if(length(value) != 1)

stop("Only assigns single values")i <- as.integer(i)if(i < 1 || i > size())

stop("index out of bounds")else

set(i-1L, value)},initialize = function(data = numeric()) {

callSuper()data <- as.double(data)n <- as.integer(max(50, length(data) * 2))reserve(n)assign(data)

})

})

Dirk Eddelbuettel Rcpp Tutorial — Part III: Advanced Rcpp

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End

Rcpp TutorialPart IV: Applications

Dr. Dirk [email protected]

[email protected]

useR! 2012Vanderbilt University

June 12, 2012

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Outline

1 RInsideBasicsMPIQtWtBuilding with RInside

2 RcppArmadilloArmadilloExample: FastLMExample: VAR(1) SimulationExample: Kalman Filter

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

The first exampleexamples/standard/rinside_sample0.cpp

We have seen this first example in part I:

#include <RInside.h> // embedded R via RInside

int main(int argc, char *argv[]) {

RInside R(argc, argv); // create embedded R inst.

R["txt"] = "Hello, world!\n"; // assign to ’txt’ in R

R.parseEvalQ("cat(txt)"); // eval string, ignore result

exit(0);}

Assign a variable, evaluate an expression—easy!

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

RInside in a nutshell

Key aspects:

RInside uses the embedding API of RAn instance of R is launched by the RInside constructorIt behaves just like a regular R processWe submit commands as C++ strings which are parsedand evaluatedRcpp is to easily get data in and out from the enclosingC++ program.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

A second example: part oneexamples/standard/rinside_sample1.cpp

#include <RInside.h> // for the embedded R via RInside

Rcpp::NumericMatrix createMatrix(const int n) {Rcpp::NumericMatrix M(n,n);for (int i=0; i<n; i++) {

for (int j=0; j<n; j++) {M(i,j) = i*10 + j;

}}return(M);

}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

A second example: part twoexamples/standard/rinside_sample1.cpp

int main(int argc, char *argv[]) {RInside R(argc, argv); // create an embedded R instance

const int mdim = 4; // let the matrices be 4 by 4; create, fillR["M"] = createMatrix(mdim); // assign data Matrix to R’s ’M’ var

std::string str ="cat(’Running ls()\n’); print(ls()); ""cat(’Showing M\n’); print(M); ""cat(’Showing colSums()\n’); Z <- colSums(M); ""print(Z); Z"; // returns Z

Rcpp::NumericVector v = R.parseEval(str); // eval, assign// now show vector on stdoutexit(0);

}

Other example files provide similar R snippets and interchange.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

A third example: Calling R plot functionsexamples/standard/rinside_sample11.cpp

#include <RInside.h> // embedded R via RInside

int main(int argc, char *argv[]) {

RInside R(argc, argv); // create an embedded R instance

// evaluate an R expression with curve()std::string cmd = "tmpf <- tempfile(’curve’); ""png(tmpf); curve(x^2, -10, 10, 200); ""dev.off(); tmpf";

// by running parseEval, we get filename backstd::string tmpfile = R.parseEval(cmd);

std::cout << "Could use plot in " << tmpfile << std::endl;unlink(tmpfile.c_str()); // cleaning up

// alternatively, by forcing a display we can plot to screencmd = "x11(); curve(x^2, -10, 10, 200); Sys.sleep(30);";R.parseEvalQ(cmd);

exit(0);}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

A fourth example: Using Rcpp modulesexamples/standard/rinside_module_sample0.cpp

#include <RInside.h> // for the embedded R via RInside// a c++ function we wish to expose to Rconst char* hello( std::string who ){

std::string result( "hello " ) ;result += who ;return result.c_str() ;

}RCPP_MODULE(bling){

using namespace Rcpp ;function( "hello", &hello );

}int main(int argc, char *argv[]) {

// create an embedded R instance -- and load Rcpp so that modules workRInside R(argc, argv, true);// load the bling moduleR["bling"] = LOAD_RCPP_MODULE(bling) ;// call it and display the resultstd::string result = R.parseEval("bling$hello(’world’)") ;std::cout << "bling$hello(’world’) = ’" << result << "’"

<< std::endl ;exit(0);

}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Other RInside standard examplesBesides ex0, ex1 and ex11

A quick overview:

ex2 loads an Rmetrics library and access dataex3 run regressions in R, uses coefs and names in C++ex4 runs a small portfolio optimisation under risk budgetsex5 creates an environment and tests for itex6 illustrations direct data access in Rex7 shows as<>() conversions from parseEval()

ex8 is another simple bi-directional data access exampleex9 makes a C++ function accessible to the embedded Rex10 creates and alters lists between R and C++ex12 uses sample() from C++

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Outline

1 RInsideBasicsMPIQtWtBuilding with RInside

2 RcppArmadilloArmadilloExample: FastLMExample: VAR(1) SimulationExample: Kalman Filter

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Parallel Computing with RInside

R is famously single-threaded.

High-performance Computing with R frequently resorts tofine-grained (multicore, doSMP) or coarse-grained (Rmpi,pvm, ...) parallelism. R spawns and controls other jobs.

Jianping Hua suggested to embed R via RInside in MPIapplications.

Now we can use the standard and well understood MPIparadigm to launch multiple R instances, each of which isindepedent of the others.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

A first exampleexamples/standard/rinside_sample2.cpp

#include <mpi.h> // mpi header#include <RInside.h> // for the embedded R via RInside

int main(int argc, char *argv[]) {

MPI::Init(argc, argv); // mpi initializationint myrank = MPI::COMM_WORLD.Get_rank(); // current node rankint nodesize = MPI::COMM_WORLD.Get_size(); // total nodes running.

RInside R(argc, argv); // embedded R instance

std::stringstream txt;txt << "Hello from node " << myrank // node information

<< " of " << nodesize << " nodes!" << std::endl;

R["txt"] = txt.str(); // assign to R var ’txt’R.parseEvalQ("cat(txt)"); // eval, ignore returns

MPI::Finalize(); // mpi finalizationexit(0);

}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

A first example: Outputexamples/standard/rinside_sample2.cpp

edd@max:/tmp$ orterun -n 8 ./rinside_mpi_sample2Hello from node 5 of 8 nodes!Hello from node 7 of 8 nodes!Hello from node 1 of 8 nodes!Hello from node 0 of 8 nodes!Hello from node 2 of 8 nodes!Hello from node 3 of 8 nodes!Hello from node 4 of 8 nodes!Hello from node 6 of 8 nodes!edd@max:/tmp$

This uses Open MPI just locally, other hosts can be added via-H node1,node2,node3.The other example(s) shows how to gather simulation resultsfrom MPI nodes.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Outline

1 RInsideBasicsMPIQtWtBuilding with RInside

2 RcppArmadilloArmadilloExample: FastLMExample: VAR(1) SimulationExample: Kalman Filter

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Application example: QtRInside examples/qt/

The question is sometimes asked how to embed RInside in alarger program.

We just added a new example using Qt:

#include <QApplication>#include "qtdensity.h"

int main(int argc, char *argv[]){

RInside R(argc, argv); // create an embedded R instance

QApplication app(argc, argv);QtDensity qtdensity(R); // pass R inst. by referencereturn app.exec();

}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Application example: Qt density sliderRInside examples/qt/

This uses standard Qt/ GUI paradigms of

radio buttonssliderstextentry

all of which sendvalues to the Rprocess whichprovides an SVG (orPNG as fallback)image that is plotted.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Application example: Qt density sliderRInside examples/qt/

The actual code is pretty standard Qt / GUI programming (andtoo verbose to be shown here).

The qtdensity.pro file is interesting as it maps the entries inthe Makefile (discussed in the next section) to the Qtstandards.

It may need an update for OS X—we have not tried that yet.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Outline

1 RInsideBasicsMPIQtWtBuilding with RInside

2 RcppArmadilloArmadilloExample: FastLMExample: VAR(1) SimulationExample: Kalman Filter

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Application example: WtRInside examples/wt/

Given the desktop application with Qt, the question arises howto deliver something similar “over the web” — and Wt helps.

Wt is similar to Qtso the code needsonly a fewchanges.Wt takes care ofall browser / appinteractions anddetermines themost featurefuldeployment.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Application example: WtRInside examples/wt/

Wt can also be“dressed up” withsimple CSSstyling (and thetext displayedcomes from anexternal XML file,further separatingcontent andpresentation).

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Outline

1 RInsideBasicsMPIQtWtBuilding with RInside

2 RcppArmadilloArmadilloExample: FastLMExample: VAR(1) SimulationExample: Kalman Filter

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Building with RInside

RInside needs headers and libraries from several projects as it

embeds R itself so we need R headers and librariesuses Rcpp so we need Rcpp headers and librariesRInside itself so we also need RInside headers and libraries

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Building with RInsideUse the Makefile in examples/standard

The Makefile is set-up to create an binary for exampleexample file supplied. It uses

R CMD config to query all of -cppflags, -ldflags,BLAS_LIBS and LAPACK_LIBS

Rscript to query Rcpp:::CxxFlags andRcpp:::LdFlags

Rscript to query RInside:::CxxFlags andRInside:::LdFlags

The qtdensity.pro file does the equivalent for Qt.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Basics MPI Qt Wt Building

Building with RInside## comment out if you need a different version of R, and set R_HOMER_HOME := $(shell R RHOME)sources := $(wildcard *.cpp)programs := $(sources:.cpp=)

## include headers and libraries for RRCPPFLAGS := $(shell $(R_HOME)/bin/R CMD config --cppflags)RLDFLAGS := $(shell $(R_HOME)/bin/R CMD config --ldflags)RBLAS := $(shell $(R_HOME)/bin/R CMD config BLAS_LIBS)RLAPACK := $(shell $(R_HOME)/bin/R CMD config LAPACK_LIBS)## if you need to set an rpath to R itself, also uncomment#RRPATH := -Wl,-rpath,$(R_HOME)/lib

## include headers and libraries for Rcpp interface classesRCPPINCL := $(shell echo ’Rcpp:::CxxFlags()’ | $(R_HOME)/bin/R --vanilla --slave)RCPPLIBS := $(shell echo ’Rcpp:::LdFlags()’ | $(R_HOME)/bin/R --vanilla --slave)

## include headers and libraries for RInside embedding classesRINSIDEINCL := $(shell echo ’RInside:::CxxFlags()’|$(R_HOME)/bin/R --vanilla --slave)RINSIDELIBS := $(shell echo ’RInside:::LdFlags()’ |$(R_HOME)/bin/R --vanilla --slave)

## compiler etc settings used in default make rulesCXX := $(shell $(R_HOME)/bin/R CMD config CXX)CPPFLAGS := -Wall $(shell $(R_HOME)/bin/R CMD config CPPFLAGS)CXXFLAGS := $(RCPPFLAGS) $(RCPPINCL) $(RINSIDEINCL)CXXFLAGS += $(shell $(R_HOME)/bin/R CMD config CXXFLAGS)LDLIBS := $(RLDFLAGS) $(RRPATH) $(RBLAS) $(RLAPACK) $(RCPPLIBS) $(RINSIDELIBS)

all: $(programs)@test -x /usr/bin/strip && strip $^

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Outline

1 RInsideBasicsMPIQtWtBuilding with RInside

2 RcppArmadilloArmadilloExample: FastLMExample: VAR(1) SimulationExample: Kalman Filter

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

ArmadilloFrom arma.sf.net and slightly edited

What is Armadillo?

Armadillo is a C++ linear algebra library aiming towards a goodbalance between speed and ease of use. Integer, floating point andcomplex numbers are supported, as well as a subset of trigonometricand statistics functions. Various matrix decompositions are provided.A delayed evaluation approach is employed (during compile time) tocombine several operations into one and reduce (or eliminate) theneed for temporaries. This is accomplished through recursivetemplates and template meta-programming.This library is useful if C++ has been decided as the language ofchoice (due to speed and/or integration capabilities).

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Armadillo highlights

Provides integer, floating point and complex vectors,matrices and fields (3d) with all the common operations.Very good documentation and examples at websitehttp://arma.sf.net, and a recent technical report(Sanderson, 2010).Modern code, building upon and extending from earliermatrix libraries.Responsive and active maintainer, frequent updates.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

RcppArmadillo highlights

Template-only builds—no linking, and available whereeverR and a compiler work (but Rcpp is needed to)!Easy to use, just add LinkingTo: RcppArmadillo,Rcpp to DESCRIPTION (i.e., no added cost beyond Rcpp)Really easy from R via RcppFrequently updated, easy to use

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Outline

1 RInsideBasicsMPIQtWtBuilding with RInside

2 RcppArmadilloArmadilloExample: FastLMExample: VAR(1) SimulationExample: Kalman Filter

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Complete file for fastLMRcppArmadillo src/fastLm.cpp

#include <RcppArmadillo.h>

extern "C" SEXP fastLm(SEXP ys, SEXP Xs) {try {arma::colvec y = Rcpp::as<arma::colvec>(ys); // direct to armaarma::mat X = Rcpp::as<arma::mat>(Xs);int df = X.n_rows - X.n_cols;arma::colvec coef = arma::solve(X, y); // fit model y ∼ Xarma::colvec res = y - X*coef; // residualsdouble s2 = std::inner_product(res.begin(), res.end(),

res.begin(), 0.0)/df; // std.errors of coefsarma::colvec std_err = arma::sqrt(s2 *

arma::diagvec(arma::pinv(arma::trans(X)*X)));return Rcpp::List::create(Rcpp::Named("coefsficients")=coef,

Rcpp::Named("stderr") = std_err,Rcpp::Named("df") = df);

} catch( std::exception &ex ) {forward_exception_to_r( ex );

} catch(...) {::Rf_error( "c++ exception (unknown reason)" );

}return R_NilValue; // -Wall

}Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Core part of fastLMRcppArmadillo src/fastLm.cpp

arma::colvec y = Rcpp::as<arma::colvec>(ys); // to armaarma::mat X = Rcpp::as<arma::mat>(Xs);

int df = X.n_rows - X.n_cols;

arma::colvec coef = arma::solve(X, y); // fit y ∼ X

arma::colvec res = y - X*coef; // residuals

double s2 = std::inner_product(res.begin(), res.end(),res.begin(), 0.0)/df; // std.err coefs

arma::colvec std_err = arma::sqrt(s2 *arma::diagvec(arma::pinv(arma::trans(X)*X)));

return Rcpp::List::create(Rcpp::Named("df") = df,Rcpp::Named("stderr") = std_err,Rcpp::Named("coefficients") = coef);

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Easy transfer from (and to) RRcppArmadillo src/fastLm.cpp

arma::colvec y = Rcpp::as<arma::colvec>(ys); // to armaarma::mat X = Rcpp::as<arma::mat>(Xs);

int df = X.n_rows - X.n_cols;

arma::colvec coef = arma::solve(X, y); // fit y ∼ X

arma::colvec res = y - X*coef; // residuals

double s2 = std::inner_product(res.begin(), res.end(),res.begin(), 0.0)/df; // std.err coefs

arma::colvec std_err = arma::sqrt(s2 *arma::diagvec(arma::pinv(arma::trans(X)*X)));

return Rcpp::List::create(Rcpp::Named("df") = df,Rcpp::Named("stderr") = std_err,Rcpp::Named("coefficients") = coef);

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Easy linear algebra via Armadillo

arma::colvec y = Rcpp::as<arma::colvec>(ys); // to armaarma::mat X = Rcpp::as<arma::mat>(Xs);

int df = X.n_rows - X.n_cols;

arma::colvec coef = arma::solve(X, y); // fit y ∼ X

arma::colvec res = y - X*coef; // residuals

double s2 = std::inner_product(res.begin(), res.end(),res.begin(), 0.0)/df; // std.err coefs

arma::colvec std_err = arma::sqrt(s2 *arma::diagvec(arma::pinv(arma::trans(X)*X)));

return Rcpp::List::create(Rcpp::Named("df") = df,Rcpp::Named("stderr") = std_err,Rcpp::Named("coefficients") = coef);

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

One note on direct casting with Armadillo

The code as just shown:

arma::colvec y = Rcpp::as<arma::colvec>(ys);arma::mat X = Rcpp::as<arma::mat>(Xs);

is very convenient, but does incur an additional copy of eachobject. A lighter variant uses two steps in which only a pointerto the object is copied:

Rcpp::NumericVector yr(ys);Rcpp::NumericMatrix Xr(Xs);int n = Xr.nrow(), k = Xr.ncol();arma::mat X(Xr.begin(), n, k, false);arma::colvec y(yr.begin(), yr.size(), false);

If performance is a concern, the latter approach may bepreferable.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Performance comparison

Running the script included in the RcppArmadillo package:

edd@max:~/svn/rcpp/pkg/RcppArmadillo/inst/examples$ r fastLm.rLoading required package: methods

test replications relative elapsed1 fLmOneCast(X, y) 5000 1.000000 0.1702 fLmTwoCasts(X, y) 5000 1.029412 0.1754 fastLmPureDotCall(X, y) 5000 1.211765 0.2063 fastLmPure(X, y) 5000 2.235294 0.3806 lm.fit(X, y) 5000 3.911765 0.6655 fastLm(frm, data = trees) 5000 40.488235 6.8837 lm(frm, data = trees) 5000 53.735294 9.135edd@max:~/svn/rcpp/pkg/RcppArmadillo/inst/examples$

NB: This includes a minor change in SVN and not yet in thereleased package.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Outline

1 RInsideBasicsMPIQtWtBuilding with RInside

2 RcppArmadilloArmadilloExample: FastLMExample: VAR(1) SimulationExample: Kalman Filter

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Example: VAR(1) Simulationexamples/part4/varSimulation.r

Lance Bachmeier started this example for his graduatestudents: Simulate a VAR(1) model row by row:

R> ## parameter and error terms used throughoutR> a <- matrix(c(0.5,0.1,0.1,0.5),nrow=2)R> e <- matrix(rnorm(10000),ncol=2)R> ## Let’s start with the R versionR> rSim <- function(coeff, errors) {+ simdata <- matrix(0, nrow(errors), ncol(errors))+ for (row in 2:nrow(errors)) {+ simdata[row,] = coeff %*% simdata[(row-1),] + errors[row,]+ }+ return(simdata)+ }R> rData <- rSim(a, e) # generated by R

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Example: VAR(1) Simulation – Compiled Rexamples/part4/varSimulation.r

With R 2.13.0, we can also compile the R function:

R> ## Now let’s load the R compiler (requires R 2.13 or later)R> suppressMessages(require(compiler))R> compRsim <- cmpfun(rSim)R> compRData <- compRsim(a,e) # gen. by R ’compiled’R> stopifnot(all.equal(rData, compRData)) # checking results

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Example: VAR(1) Simulation – RcppArmadilloexamples/part4/varSimulation.r

R> ## Now load ’inline’ to compile C++ code on the flyR> suppressMessages(require(inline))R> code <- ’+ arma::mat coeff = Rcpp::as<arma::mat>(a);+ arma::mat errors = Rcpp::as<arma::mat>(e);+ int m = errors.n_rows; int n = errors.n_cols;+ arma::mat simdata(m,n);+ simdata.row(0) = arma::zeros<arma::mat>(1,n);+ for (int row=1; row<m; row++) {+ simdata.row(row) = simdata.row(row-1) *+ trans(coeff)+errors.row(row);+ }+ return Rcpp::wrap(simdata);+ ’R> ## create the compiled functionR> rcppSim <- cxxfunction(signature(a="numeric",e="numeric"),+ code,plugin="RcppArmadillo")R> rcppData <- rcppSim(a,e) # generated by C++ codeR> stopifnot(all.equal(rData, rcppData)) # checking results

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Example: VAR(1) Simulation – RcppArmadilloexamples/part4/varSimulation.r

R> ## now load the rbenchmark package and compare all threeR> suppressMessages(library(rbenchmark))R> res <- benchmark(rcppSim(a,e),+ rSim(a,e),+ compRsim(a,e),+ columns=c("test", "replications",+ "elapsed", "relative"),+ order="relative")R> print(res)

test replications elapsed relative1 rcppSim(a, e) 100 0.038 1.00003 compRsim(a, e) 100 2.011 52.92112 rSim(a, e) 100 4.148 109.1579R>

So more than fifty times faster than byte-compiled R and morethan hundred times faster than R code.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Example: VAR(1) Simulation – RcppArmadilloexamples/part4/varSimulation.r

R> ## now load the rbenchmark package and compare all threeR> suppressMessages(library(rbenchmark))R> res <- benchmark(rcppSim(a,e),+ rSim(a,e),+ compRsim(a,e),+ columns=c("test", "replications",+ "elapsed", "relative"),+ order="relative")R> print(res)

test replications elapsed relative1 rcppSim(a, e) 100 0.038 1.00003 compRsim(a, e) 100 2.011 52.92112 rSim(a, e) 100 4.148 109.1579R>

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Outline

1 RInsideBasicsMPIQtWtBuilding with RInside

2 RcppArmadilloArmadilloExample: FastLMExample: VAR(1) SimulationExample: Kalman Filter

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Kalman Filter

The Mathworks has a nice example1 of a classic ’objecttracking’ problem showing gains from going from Matlab codeto compiled C code.The example is short:

% Copyright 2010 The MathWorks, Inc.function y = kalmanfilter(z)% #codegen

dt=1;% Initialize state transition matrixA=[1 0 dt 0 0 0;... % [x ]

0 1 0 dt 0 0;... % [y ]0 0 1 0 dt 0;... % [Vx]0 0 0 1 0 dt;... % [Vy]0 0 0 0 1 0 ;... % [Ax]0 0 0 0 0 1 ]; % [Ay]

H = [ 1 0 0 0 0 0; 0 1 0 0 0 0 ];Q = eye(6);R = 1000 * eye(2);persistent x_est p_estif isempty(x_est)

x_est = zeros(6, 1);p_est = zeros(6, 6);

end

% Predicted state and covariancex_prd = A * x_est;p_prd = A * p_est * A’ + Q;% EstimationS = H * p_prd’ * H’ + R;B = H * p_prd’;klm_gain = (S \ B)’;% Estimated state and covariancex_est = x_prd+klm_gain*(z-H*x_prd);p_est = p_prd-klm_gain*H*p_prd;% Compute the estimated measurementsy = H * x_est;

end % of the function

1http://www.mathworks.com/products/matlab-coder/demos.html?file=/products/demos/

shipping/coder/coderdemo_kalman_filter.html

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Kalman Filter: In REasy enough – first naive solution

FirstKalmanR <- function(pos) {

kf <- function(z) {dt <- 1

A <- matrix(c(1, 0, dt, 0, 0, 0, # x0, 1, 0, dt, 0, 0, # y0, 0, 1, 0, dt, 0, # Vx0, 0, 0, 1, 0, dt, # Vy0, 0, 0, 0, 1, 0, # Ax0, 0, 0, 0, 0, 1), # Ay

6, 6, byrow=TRUE)H <- matrix( c(1, 0, 0, 0, 0, 0,

0, 1, 0, 0, 0, 0),2, 6, byrow=TRUE)

Q <- diag(6)R <- 1000 * diag(2)

N <- nrow(pos)y <- matrix(NA, N, 2)

## predicted state and covriancexprd <- A %*% xestpprd <- A %*% pest %*% t(A) + Q

## estimationS <- H %*% t(pprd) %*% t(H) + RB <- H %*% t(pprd)## kalmangain <- (S \ B)’kg <- t(solve(S, B))

## est. state and cov, assign to vars in parent envxest <<- xprd + kg %*% (z-H%*%xprd)pest <<- pprd - kg %*% H %*% pprd

## compute the estimated measurementsy <- H %*% xest

}

xest <- matrix(0, 6, 1)pest <- matrix(0, 6, 6)

for (i in 1:N) {y[i,] <- kf(t(pos[i„drop=FALSE]))

}

invisible(y)}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Kalman Filter: In REasy enough – with some minor refactoring

KalmanR <- function(pos) {

kf <- function(z) {## predicted state and covriancexprd <- A %*% xestpprd <- A %*% pest %*% t(A) + Q

## estimationS <- H %*% t(pprd) %*% t(H) + RB <- H %*% t(pprd)## kg <- (S \ B)’kg <- t(solve(S, B))

## estimated state and covariance## assigned to vars in parent envxest <<- xprd + kg %*% (z-H%*%xprd)pest <<- pprd - kg %*% H %*% pprd

## compute the estimated measurementsy <- H %*% xest

}dt <- 1

A <- matrix(c(1, 0, dt, 0, 0, 0, # x0, 1, 0, dt, 0, 0, # y0, 0, 1, 0, dt, 0, # Vx0, 0, 0, 1, 0, dt, # Vy0, 0, 0, 0, 1, 0, # Ax0, 0, 0, 0, 0, 1),# Ay6, 6, byrow=TRUE)

H <- matrix(c(1, 0, 0, 0, 0, 0,0, 1, 0, 0, 0, 0),

2, 6, byrow=TRUE)Q <- diag(6)R <- 1000 * diag(2)

N <- nrow(pos)y <- matrix(NA, N, 2)

xest <- matrix(0, 6, 1)pest <- matrix(0, 6, 6)

for (i in 1:N) {y[i,] <- kf(t(pos[i„drop=FALSE]))

}invisible(y)

}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Kalman Filter: In C++Using a simple class

using namespace arma;

class Kalman {private:mat A, H, Q, R, xest, pest;double dt;

public:// constructor, sets up data structuresKalman() : dt(1.0) {A.eye(6,6);A(0,2)=A(1,3)=A(2,4)=A(3,5)=dt;H.zeros(2,6);H(0,0) = H(1,1) = 1.0;Q.eye(6,6);R = 1000 * eye(2,2);xest.zeros(6,1);pest.zeros(6,6);

}

// sole member function: estimate modelmat estimate(const mat & Z) {unsigned int n = Z.n_rows,

k = Z.n_cols;mat Y = zeros(n, k);

for (unsigned int i = 0; i<n; i++) {colvec z = Z.row(i).t();

// predicted state and covriancemat xprd = A * xest;mat pprd = A * pest * A.t() + Q;

// estimationmat S = H * pprd.t() * H.t() + R;mat B = H * pprd.t();mat kg = trans(solve(S, B));

// estimated state and covariancexest = xprd + kg * (z - H * xprd);pest = pprd - kg * H * pprd;

// compute the estimated measurementscolvec y = H * xest;Y.row(i) = y.t();

}return Y;

}};

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Kalman Filter in C++Trivial to use from R

Given the code from the previous slide in a text variablekalmanClass, we just do thiskalmanSrc <- ’

mat Z = as<mat>(ZS); // passed from RKalman K;mat Y = K.estimate(Z);return wrap(Y);

KalmanCpp <- cxxfunction(signature(ZS="numeric"),body=kalmanSrc,include=kalmanClass,plugin="RcppArmadillo")

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Kalman Filter: PerformanceQuite satisfactory relative to R

Even byte-compiled ’better’ R version is 66 times slower:R> FirstKalmanRC <- cmpfun(FirstKalmanR)R> KalmanRC <- cmpfun(KalmanR)R>R> stopifnot(identical(KalmanR(pos), KalmanRC(pos)),+ all.equal(KalmanR(pos), KalmanCpp(pos)),+ identical(FirstKalmanR(pos), FirstKalmanRC(pos)),+ all.equal(KalmanR(pos), FirstKalmanR(pos)))R>R> res <- benchmark(KalmanR(pos), KalmanRC(pos),+ FirstKalmanR(pos), FirstKalmanRC(pos),+ KalmanCpp(pos),+ columns = c("test", "replications",+ "elapsed", "relative"),+ order="relative",+ replications=100)R>R> print(res)

test replications elapsed relative5 KalmanCpp(pos) 100 0.087 1.00002 KalmanRC(pos) 100 5.774 66.36781 KalmanR(pos) 100 6.448 74.11494 FirstKalmanRC(pos) 100 8.153 93.71263 FirstKalmanR(pos) 100 8.901 102.3103

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Armadillo FastLM VAR(1) Kalman

Kalman Filter: FigureLast but not least we can redo the plot as well

−0.5 0.0 0.5 1.0

−1.

0−

0.5

0.0

0.5

1.0

Object Trajectory and Kalman Filter Estimate

x

y

TrajectoryEstimate

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

Outline

3 RcppEigenOverviewExample

4 RcppGSLOverviewExample

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

RcppEigen

RcppEigen wraps the Eigen library for linear algebra.

Eigen is similar to Armadillo, and very highly optimised—byinternal routines replacing even the BLAS for performance.

Eigen is also offering a more complete API than Armadillo (but Iprefer to work with the simpler Armadillo, most of the time).

RcppEigen is written mostly by Doug Bates who needs sparsematrix support for his C++ rewrite of lme4 (e.g. lme4eigen).

Eigen can be faster than Armadillo. Andreas Alfons’ CRANpackage robustHD (using Armadillo) with a drop-inreplacement sparseLTSEigen sees gain of 1/4 to 1/3.

However, Eigen is not always available on all platforms as therecan be issues with older compilers (eg on OS X).

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

Outline

3 RcppEigenOverviewExample

4 RcppGSLOverviewExample

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

RcppEigen’s fastLmSlightly simplified / shortened

const MMatrixXd X(as<MMatrixXd>(Xs));const MVectorXd y(as<MVectorXd>(ys));Index n = X.rows(), p = X.cols();lm ans = do_lm(X, y, ::Rf_asInteger(type));NumericVector coef = wrap(ans.coef());List dimnames = NumericMatrix(Xs).attr("dimnames");VectorXd resid = y - ans.fitted();double s2 = resid.squaredNorm()/ans.df();PermutationType Pmat = PermutationType(p);Pmat.indices() = ans.perm();VectorXd dd = Pmat * ans.unsc().diagonal();ArrayXd se = (dd.array() * s2).sqrt();return List::create(_["coefficients"] = coef,

_["se"] = se,_["rank"] = ans.rank(),_["df.residual"] = ans.df(),_["perm"] = ans.perm(),_["residuals"] = resid,_["s2"] = s2,_["fitted.values"] = ans.fitted(),_["unsc"] = ans.unsc());

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

RcppEigen’s fastLm (cont.)The lm alternatives

Doug defines a base class lm from which the following classesderive:

LLt (standard Cholesky decomposition)LDLt (robust Cholesky decompostion with pivoting)SymmEigen (standard Eigen-decomposition)QR (standard QR decomposition)ColPivQR (Householder rank-revealing QR decompositionwith column-pivoting)SVD (standard SVD decomposition)

The example file lmBenchmark.R in the package runs throughthese.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

RcppEigen’s fastLm (cont.)The benchmark results

lm benchmark for n = 100000 and p = 40: nrep = 20test relative elapsed user.self sys.self

3 LDLt 1.000000 0.911 0.91 0.007 LLt 1.000000 0.911 0.91 0.005 SymmEig 2.833150 2.581 2.17 0.406 QR 5.050494 4.601 4.17 0.412 ColPivQR 5.102086 4.648 4.20 0.438 arma 6.837541 6.229 6.00 0.001 lm.fit 9.189901 8.372 7.12 1.144 SVD 32.183315 29.319 28.44 0.769 GSL 113.680571 103.563 102.42 0.53

This improves significantly over the Armadillo-based solution.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

One last remark on the fastLm routines

Doug sometimes reminds us about the occassional finedifferences between statistical numerical analysis and standardnumerical analysis.

Pivoting schemes are a good example. R uses a customdecomposition (with pivoting) inside of lm() which makes itboth robust and precise, particularly for rank-deficient matrices.

The example for fastLm in both RcppArmadillo andRcppEigen provides an illustration.

If you are really sure your data is well-behaved, then using afaster (non-pivoting) scheme as in RcppArmadillo

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

Outline

3 RcppEigenOverviewExample

4 RcppGSLOverviewExample

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

RcppGSL

RcppGSL is a convenience wrapper for accessing the GNUGSL, particularly for vector and matrix functions.

Given that the GSL is a C library, we need to

do memory management and free objectsarrange for the GSL linker to be found

RcppGSL may still be a convenient tool for programmers morefamiliar with C than C++ wanting to deploy GSL algorithms.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

Outline

3 RcppEigenOverviewExample

4 RcppGSLOverviewExample

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

Vector norm example—c.f. GSL manualexamples/part4/gslNorm.cpp

#include <RcppGSL.h>#include <gsl/gsl_matrix.h>#include <gsl/gsl_blas.h>

extern "C" SEXP colNorm(SEXP sM) {try {RcppGSL::matrix<double> M = sM; // SEXP to gsl data structureint k = M.ncol();Rcpp::NumericVector n(k); // to store resultsfor (int j = 0; j < k; j++) {RcppGSL::vector_view<double> colview =

gsl_matrix_column (M, j);n[j] = gsl_blas_dnrm2(colview);

}M.free();return n; // return vector

} catch( std::exception &ex ) {forward_exception_to_r( ex );

} catch(...) {::Rf_error( "c++ exception (unknown reason)" );

}return R_NilValue; // -Wall

}Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

Core part of exampleexamples/part4/gslNorm.cpp

RcppGSL::matrix<double> M = sM; // SEXP to GSL dataint k = M.ncol();Rcpp::NumericVector n(k); // to store results

for (int j = 0; j < k; j++) {RcppGSL::vector_view<double> colview =

gsl_matrix_column (M, j);n[j] = gsl_blas_dnrm2(colview);

}M.free();return n; // return vector

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Overview Example

Core part of exampleUsing standard GSL functions: examples/part4/gslNorm.cpp

RcppGSL::matrix<double> M = sM; // SEXP to GSL dataint k = M.ncol();Rcpp::NumericVector n(k); // to store results

for (int j = 0; j < k; j++) {RcppGSL::vector_view<double> colview =

gsl_matrix_column (M, j);n[j] = gsl_blas_dnrm2(colview);

}M.free();return n; // return vector

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Gibbs Sampler Example

Darren Wilkinson wrote a couple of blog posts illustrating theperformance of different implementations (C, Java, Python, ...)for a simple MCMC Gibbs sampler of this bivariate density::

f (x , y) = kx2 exp(−xy2 − y2 + 2y − 4x)

with conditional distributions

f (x |y) ∼ Gamma(3, y2 + 4)

f (y |x) ∼ N(

11 + x

,1

2(1 + x)

)

i.e. we need repeated RNG draws from both a Gamma and aGaussian distribution.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Gibbs Sampler Example

Sanjog Misra then sent me working R and C++ versions which Iextended. In R we use:

Rgibbs <- function(N,thin) {mat <- matrix(0,ncol=2,nrow=N)x <- 0y <- 0for (i in 1:N) {

for (j in 1:thin) {x <- rgamma(1,3,y*y+4)y <- rnorm(1,1/(x+1),1/sqrt(2*(x+1)))

}mat[i,] <- c(x,y)

}mat

}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Gibbs Sampler Example (cont.)

The C++ version using Rcpp closely resembles the R version::gibbscode <- ’

// n and thin are SEXPs which the Rcpp::as function maps to C++ varsint N = as<int>(n);int thn = as<int>(thin);int i,j;NumericMatrix mat(N, 2);RNGScope scope; // Initialize Random number generatordouble x=0, y=0;for (i=0; i<N; i++) {

for (j=0; j<thn; j++) {x = ::Rf_rgamma(3.0,1.0/(y*y+4));y = ::Rf_rnorm(1.0/(x+1),1.0/sqrt(2*x+2));

}mat(i,0) = x;mat(i,1) = y;

}return mat; // Return to R

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Gibbs Sampler Example (cont.)

We compile the C++ function:# Compile and LoadRcppGibbs <- cxxfunction(signature(n="int",

thin = "int"),gibbscode, plugin="Rcpp")

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Gibbs Sampler Example (cont.)

We also create a similar variant using the GSL’s randomnumber generators (as in Darren’s example):gslgibbscode <- ’

int N = as<int>(ns);int thin = as<int>(thns);int i, j;gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);double x=0, y=0;NumericMatrix mat(N, 2);for (i=0; i<N; i++) {

for (j=0; j<thin; j++) {x = gsl_ran_gamma(r,3.0,1.0/(y*y+4));y = 1.0/(x+1)+gsl_ran_gaussian(r,1.0/sqrt(2*x+2));

}mat(i,0) = x;mat(i,1) = y;

}gsl_rng_free(r);return mat; // Return to R

’Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Gibbs Sampler Example (cont.)

We compile the GSL / C function:gslgibbsincl <- ’

#include <gsl/gsl_rng.h>#include <gsl/gsl_randist.h>

using namespace Rcpp; // just to be explicit’

## Compile and LoadGSLGibbs <- cxxfunction(signature(ns="int",

thns = "int"),body=gslgibbscode,includes=gslgibbsincl,plugin="RcppGSL")

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R Rcpp RcppGSL Performance

Gibbs Sampler Example (cont.)

The result show a dramatic gain from the two compiled versionrelative to the R version, and the byte-compiled R version:

test repl. elapsed relative user.self sys.self4 GSLGibbs(N, thn) 10 7.918 1.000000 7.87 0.003 RcppGibbs(N, thn) 10 12.300 1.553423 12.25 0.002 RCgibbs(N, thn) 10 306.349 38.690200 305.07 0.111 Rgibbs(N, thn) 10 412.467 52.092321 410.76 0.18

The gain of the GSL version relative to the Rcpp is due almostentirely to a much faster RNG for the gamma distribution asshown by timeRNGs.R.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Accelerating Monte Carlo

Albert. Bayesian Computationwith R, 2nd ed. Springer, 2009

Albert introduces simulations with asimple example in the first chapter.

We will study this example and translateit to R using RcppArmadillo (and Rcpp).

The idea is to, for a given level α, andsizes n and m, draw a number N ofsamples at these sizes, compoute at-statistic and record if the test statisticexceeds the theoretical critical valuegiven the parameters.

This allows us to study the impact ofvarying α, N or M — as well as varyingparameters or even families of therandom vectors.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Restating the problem

With two samples x1, . . . , xm and y1, . . . , yn we can test

H0 : µx = µy

With sample means X and Y , and sx and y as respectivestandard deviations, the standard test is

T =X − Y

sP√

1/m + 1/n

whew sp is the pooled standard deviation

sp =

√(m − 1)s2

x + (n − 1)s2y

m + n − 2

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Restating the problem

Under H0, we have T ∼ t(m + n − 2) provided thatxi and x + i are NIDthe standard deviations of populations x and y are equal.

For a given level α, we can reject H if

|T | ≥ tn+m−2,α/2

But happens when we haveunequal population variances, ornon-normal distributions?

Simulations can tell us.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Basic R versionCore function: examples/part4/montecarlo.r

## Section 1.3.3## simulation algorithm for normal populationssim1_3_3_R <- function() {

alpha <- .1; m <- 10; n <- 10 # sets alpha, m, nN <- 10000 # sets nb of simsn.reject <- 0 # number of rejectionscrit <- qt(1-alpha/2,n+m-2)for (i in 1:N) {

x <- rnorm(m,mean=0,sd=1) # simulates xs from population 1y <- rnorm(n,mean=0,sd=1) # simulates ys from population 2t.stat <- tstatistic(x,y) # computes the t statisticif (abs(t.stat)>crit)

n.reject=n.reject+1 # reject if |t| exceeds critical pt}true.sig.level <- n.reject/N # est. is proportion of rejections

}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Basic R versionHelper function for t-statistic: examples/part4/montecarlo.r

## helper functiontstatistic <- function(x,y) {

m <- length(x)n <- length(y)sp <- sqrt(((m-1)*sd(x)^2 + (n-1)*sd(y)^2) / (m+n-2))t.stat <- (mean(x) - mean(y)) / (sp*sqrt(1/m + 1/n))return(t.stat)

}

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

RcppArmadillo versionMain function: examples/part4/montecarlo.r

sim1_3_3_arma <- cxxfunction(, plugin="RcppArmadillo",inc=tstat_arma, body=’

RNGScope scope; // properly deal with RNGsdouble alpha = 0.1;int m = 10, n = 10; // sets alpha, m, nint N = 10000; // sets the number of simsdouble n_reject = 0; // counter of num. of rejectsdouble crit = ::Rf_qt(1.0-alpha/2.0, n+m-2.0,true,false);for (int i=0; i<N; i++) {NumericVector x = rnorm(m, 0, 1); // sim xs from pop 1NumericVector y = rnorm(n, 0, 1); // sim ys from pop 2double t_stat = tstatistic(Rcpp::as<arma::vec>(x),

Rcpp::as<arma::vec>(y));if (fabs(t_stat) > crit)n_reject++; // reject if |t| exceeds critical pt

}double true_sig_level = 1.0*n_reject / N; // est. prop rejectsreturn(wrap(true_sig_level));

’)

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

RcppArmadillo versionHelper function for t-statistic: : examples/part4/montecarlo.r

tstat_arma <- ’double tstatistic(const NumericVector &x,

const NumericVector &y) {int m = x.size();int n = y.size();double sp = sqrt( ( (m-1.0)*pow(sd(x),2) +

(n-1)*pow(sd(y),2) ) / (m+n-2.0) );double t_stat = (mean(x)-mean(y))/(sp*sqrt(1.0/m+1.0/n));return(t_stat);

}’

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Rcpp version—using sugar functions mean, sd, ...Main function: examples/part4/montecarlo.r

sim1_3_3_rcpp <- cxxfunction(, plugin="Rcpp",inc=tstat_rcpp, body=’

RNGScope scope; // properly deal with RNG settingsdouble alpha = 0.1;int m = 10, n = 10; // sets alpha, m, nint N = 10000; // sets the number of simulationsdouble n_reject = 0; // counter of num. of rejectionsdouble crit = ::Rf_qt(1.0-alpha/2.0, n+m-2.0, true, false);for (int i=0; i<N; i++) {NumericVector x = rnorm(m, 0, 1); // sim xs from pop 1NumericVector y = rnorm(n, 0, 1); // sim ys from pop 2double t_stat = tstatistic(x, y);if (fabs(t_stat) > crit)n_reject++; // reject if |t| exceeds critical pt

}double true_sig_level = 1.0*n_reject / N; // est. prop rejectsreturn(wrap(true_sig_level));

’)

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Rcpp version—using SVN version with mean, sd, ...Helper function: examples/part4/montecarlo.r

tstat_rcpp <- ’double tstatistic(const NumericVector &x,

const NumericVector &y) {int m = x.size();int n = y.size();double sp = sqrt( ( (m-1.0)*pow(sd(x),2) +

(n-1)*pow(sd(y),2) ) / (m+n-2.0) );double t_stat = (mean(x)-mean(y))/(sp*sqrt(1.0/m+1.0/n));return(t_stat);

}’

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Outline

5 Example: Gibbs SamplerIntroRRcppRcppGSLPerformance

6 Example: SimulationsIntroRRcppArmadilloRcppPerformance

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Benchmark resultsexamples/part4/montecarlo.r

R> library(rbenchmark)R> res <- benchmark(sim1_3_3_R(),+ sim1_3_3_Rcomp(),+ sim1_3_3_arma(),+ sim1_3_3_rcpp(),+ columns=c("test", "replications",+ "elapsed", "relative",+ "user.self"),+ order="relative")R> res

test replications elapsed relative user.self3 sim1_3_3_arma() 100 2.118 1.00000 2.124 sim1_3_3_rcpp() 100 2.192 1.03494 2.191 sim1_3_3_R() 100 153.772 72.60246 153.702 sim1_3_3_Rcomp() 100 154.251 72.82861 154.19R>

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Benchmark results

R> restest replications elapsed relative user.self

3 sim1_3_3_arma() 100 2.118 1.00000 2.124 sim1_3_3_rcpp() 100 2.192 1.03494 2.191 sim1_3_3_R() 100 153.772 72.60246 153.702 sim1_3_3_Rcomp() 100 154.251 72.82861 154.19R>

In this example, the R compiler does not help at all. Thedifference between RcppArmadillo and Rcpp is neglible.

Suggestions (by Albert): replace n, m, standard deviations ofNormal RNG, replace Nornal RNG, ... which, thanks to Rcppand ’Rcpp sugar’ is a snap.

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End Intro R RcppArmadillo Rcpp Performance

Simulation resultsexamples/part4/montecarlo.r

Albert reports this table:

Populations True Sign. Level

Normal pop. with equal spreads 0.0986Normal pop. with unequal spreads 0.1127t(4) distr. with equal spreads 0.0968Expon. pop. with equal spreads 0.1019Normal + exp. pop. with unequal spreads 0.1563

Table: True significance level of t-test computed by simulation;standard error of each estimate is approximately 0.003.

Our simulations are ≈ 70-times faster, so we can increase thenumber of simulation by 100 and reduce the standard error to√

0.1× 0.9/1,000,000 = 0.0003.Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications

RInside Arma Eigen GSL Ex:Gibbs Ex:Sims End

That’s it, folks!

Want to learn more ?

Check all the vignettes

Ask questions on the Rcpp-devel mailing list

Hands-on training courses and consulting are available

Romain François [email protected] Eddelbuettel [email protected]

Dirk Eddelbuettel Rcpp Tutorial — Part IV: Applications