---
title: "Introduction to rTRNG"
author: "Riccardo Porreca, Roland Schmid"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Introduction to rTRNG}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---


```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, collapse = TRUE)
linking_ok <- rTRNG::check_rTRNG_linking()
```


### Introduction

Monte Carlo simulations provide a powerful computational approach to address a 
wide variety of problems in several domains, such as physical sciences, 
engineering, computational biology and finance. The independent-samples and 
large-scale nature of Monte Carlo simulations make the corresponding computation
suited for parallel execution, at least in theory. In practice, pseudo-random 
number generators (RNGs) are intrinsically sequential. This often prevents
having a parallel Monte Carlo algorithm that is *playing fair*, meaning that
results are independent of the architecture, parallelization techniques and
number of parallel processes.

**rTRNG** is an R package for advanced parallel Random Number Generation in
R. It relies on **[TRNG](https://numbercrunch.de/trng/)** (Tina's Random Number
Generator), a state-of-the-art C++ pseudo-random number generator library for
sequential and parallel Monte Carlo simulations.  In particular, *parallel*
random number engines provided by TRNG can be manipulated by `jump` and `split`
operations. These allow to `jump` ahead by an arbitrary number of steps and to
`split` a sequence into any desired sub-sequence(s), thus enabling techniques
such as *block-splitting* and *leapfrogging* suitable to parallel algorithms.

Package **rTRNG** provides the R users with access to the functionality of the
underlying TRNG C++ library, both in R and as part of other projects combining R
with C++.


### TRNG.Random

The TRNG.Random functionality (see `?TRNG.Random`) provides a base-R-like access
to TRNG random number engines by setting and manipulating the current engine in 
use.
```{r TRNG.Random}
library(rTRNG)
TRNGkind("yarn2")
TRNGseed(117)
TRNGjump(5) # advance by 5 the internal state
TRNGsplit(3, 2) # subsequence: one element every 3 starting from the 2nd
```
Random variates from the current engine are then generated using functions
`r<dist>_trng`, e.g. `runif_trng` for the uniform distribution.
```{r runif_trng}
x <- runif_trng(10)
x
```


### TRNG.Engine

Random number engines can be explicitly created and manipulated using reference 
objects from a number of classes (see `?TRNG.Engine`), e.g. `yarn2`.
```{r TRNG.Engine}
rng <- yarn2$new()
rng$seed(117)
# alternative: rng <- yarn2$new(117) 
rng$jump(5) 
rng$split(3, 2) 
```
The engine object is then passed as `engine` argument of any `r<dist>_trng`
function.
```{r runif_trng-engine}
x <- runif_trng(10, engine = rng)
x
```


### Parallel generation

The parallel nature of TRNG random number engines allows *fair-playing*
multi-threaded generation of random variates, with guaranteed equivalence to a
purely-sequential generation. Parallel generation is available in `r<dist>_trng`
with argument `parallelGrain > 0` and relies on `RcppParallel`, where the number
of parallel threads is controlled via `RcppParallel::setThreadOptions`.
```{r ex-parallelGrain}
TRNGseed(117)
RcppParallel::setThreadOptions(numThreads = 2)
x_parallel <- runif_trng(1e5, parallelGrain = 100)
TRNGseed(117)
x_serial <- runif_trng(1e5)
identical(x_serial, x_parallel)
```


### Standalone C++

C++ code using the C++ TRNG library and headers shipped with **rTRNG** can
easily be compiled, specifying the `Rcpp::depends` attribute that allows
`Rcpp::sourceCpp` to link correctly against the library. Moreover,
`Rcpp::plugins(cpp11)` is needed to enforce the C++11 standard required by TRNG
>= 4.22.

```{Rcpp sourceCpp, eval=linking_ok}
// [[Rcpp::depends(rTRNG)]]
// TRNG >= 4.22 requires C++11
// [[Rcpp::plugins(cpp11)]]
#include <Rcpp.h>
#include <trng/yarn2.hpp>
#include <trng/uniform_dist.hpp>
using namespace Rcpp;
using namespace trng;
// [[Rcpp::export]]
NumericVector exampleCpp() {
  yarn2 rng;
  rng.seed(117);
  // alternative: yarn2 rng(117); 
  rng.jump(5);
  rng.split(3, 1); // note the C++ 0-based index for the subsequence
  NumericVector x(10);
  uniform_dist<> unif(0, 1);
  for (unsigned int i = 0; i < 10; i++) {
    x[i] = unif(rng);
  }
  return x;
}
/*** R
exampleCpp()
*/
```
```{r sourceCpp-R, echo=FALSE, eval=linking_ok}
exampleCpp()
```


### R packages

Creating an R package with C++ code using the TRNG library and headers through
**rTRNG** is achieved by

- adding `Imports: rTRNG` and `LinkingTo: rTRNG` to the DESCRIPTION file
- importing one symbol in the NAMESPACE: `importFrom(rTRNG, TRNG.Version)`
- enforcing compilation using C++11 in Makevars[.win] via `CXX_STD = CXX11`
- setting the relevant linker flags in Makevars[.win] via `rTRNG::LdFlags()`
    - Makevars: `PKG_LIBS += $(shell ${R_HOME}/bin/Rscript -e "rTRNG::LdFlags()")`
    - Makevars.win: `PKG_LIBS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "rTRNG::LdFlags()")`


### Note about C++ code on macOS

C++ code using the TRNG library (sourced via `Rcpp::sourceCpp` or part of an R
package) might fail on certain systems due to issues with building and linking
against **rTRNG**. This is typically the case for **macOS**, and can generally
be checked by running

```{r check-linking, eval=FALSE}
rTRNG::check_rTRNG_linking()
```
