--- title: "Rcpp" author: "JJB + course" output: html_document: toc: true toc_float: collapsed: false --- # Rcpp ## Example: Saying hello {Rcpp hello_world_ex} #include using namespace Rcpp; // [[Rcpp::export]] void hello_world_cpp() { Rcout << "Hello R/C++ World!\n"; }  ## Example: Embedding Rcpp into RMarkdown. To use _Rcpp_ code within _RMarkdown, we change {R} to {Rcpp} within the code chunk block. ## Example: Calling the C++ Function within *R* {r} # Call C++ Code like a normal R function hello_world_cpp()  # Practical Usage ## Example: Embedding is_odd_cpp() in _R_ {Rcpp} #include using namespace Rcpp; // [[Rcpp::export]] bool is_odd_cpp(int n = 10) {// function definition bool v = (n % 2 == 1); // modulus check return v; // return result }  ## Example: Calling is_odd_cpp() in _R_ {r} is_odd_cpp() is_odd_cpp(10) is_odd_cpp(3)  ## Example: Vectorizing Is Odd in C++ int can only hold one value. What if we wanted to process a vector? {Rcpp} #include using namespace Rcpp; // [[Rcpp::export]] LogicalVector is_odd_vec_cpp(IntegerVector x) { int n = x.size(); // number of elements LogicalVector v(n); // logical vector for(int i = 0; i < n; i++) { // process each value v[i] = (x[i] % 2 == 1); // modulus check } return v; }  Differences: {r, eval = FALSE} is_odd_cpp(1:5) # Error in is_odd_cpp(1:5) : Expecting a single value: [extent=5].  {r} is_odd_vec_cpp(1:5)  ## Example: Loops Consider the mean: {r} mean_r = function(x) { sum_r = 0 for (i in seq_along(x)) { sum_r = sum_r + x[i] } sum_r / length(x) }  **C++** Implementation {Rcpp mean} #include using namespace Rcpp; // Import Statements // [[Rcpp::export]] double mean_cpp(NumericVector x) { // Declaration int n = x.size(); // Find the vector length double sum_x = 0; // Set up storage for(int i = 0; i < n; ++i) { // For Loop in C++ // Shorthand for sum_x = sum_x + x[i]; sum_x += x[i]; } return sum_x / n; // Return division }  Verifying equality: {r} # Done in *R* set.seed(112) # Set seed x = rnorm(10) # Generate data all.equal(mean_cpp(x), mean_r(x)) # Test Functions  ### Exercise: Creating a scalar version of is_divisible_by() Modify the is_odd_cpp() to is_divisible_by(), which checks to see if a number is divisible by another. {Rcpp} #include using namespace Rcpp; // [[Rcpp::export]] bool is_divisible_by(int num, int divisor) { bool result = (num % divisor == 0); return result; }  {r} is_divisible_by  {r} is_divisible_by(4, 2) is_divisible_by(5, 2) is_divisible_by(5, 3)  ## Example: Squaring Numbers The squaring operation switches from base^exp to pow(base, exp); {Rcpp} #include using namespace Rcpp; // [[Rcpp::export]] NumericVector square_numbers(NumericVector x) { int n = x.size(); NumericVector res(n); for(int i = 0; i < n; i++) { res[i] = pow(x[i], 2.0); // x^2 } return res; }  ### Exercise: Compute the Sum of Squares Modify the squaring operation given previously such that is computes the sum of squares for $x$. $\sum\limits_{i = 1}^n {{{\left( {{x_i} - \bar x} \right)}^2}}$ **Recall:** C++ indices start at 0 **NOT** 1. {Rcpp} #include using namespace Rcpp; // Import Statements // [[Rcpp::export]] double mean_cpp(NumericVector x) { // Declaration int n = x.size(); // Find the vector length double sum_x = 0; // Set up storage for(int i = 0; i < n; ++i) { // For Loop in C++ // Shorthand for sum_x = sum_x + x[i]; sum_x += x[i]; } return sum_x / n; // Return division } // [[Rcpp::export]] double sum_of_squares(NumericVector x){ int n = x.size(); double summed_value = 0; double x_mean = mean_cpp(x); for(int i = 0; i< n; i++) { summed_value = summed_value + pow((x[i] - x_mean), 2.0); } return summed_value; }  # Behind the Scenes: Proxy Model ## Example: {Rcpp} // Written in C++ // Import Statements #include using namespace Rcpp; // Assume numeric type // [[Rcpp::export]] void ref_update_num(NumericVector x) { x = x + 1; } // Assume integer type // [[Rcpp::export]] void ref_update_int(IntegerVector x) { x = x + 1; }  {r} # In R x = c(-8L, 2L) # Note: Neither function will output since there is no return ref_update_num(x) # Call numeric update x # Same values!!! ref_update_int(x) # Call numeric update x # Different values!!!  ## Example: Type Sensitivity {r} add_r = function(a, b) { return(a + b) } add_r(0L, 2L) # Remember L means integer! add_r(2.5, 1.1) # Double/numeric  {Rcpp, eval = TRUE} #include using namespace Rcpp; // Import Statements // [[Rcpp::export]] double add_cpp(double a, double b) { // Declaration double out = a + b; // Add a to b return out; // Return output }  {r} add_cpp(0L, 2L) # Integers into double add_cpp(2.5, 1.1) # Double into double  ### Example: Calling a C++ Function with different types {Rcpp} #include using namespace Rcpp; // Import Statements // [[Rcpp::export]] double add_cpp(double a, double b) { // Declaration double out = a + b; // Add a to b return out; // Return output } // [[Rcpp::export]] int add_cpp_int(int a, int b) { // Declaration return add_cpp(a, b); // Call previous function }  {r} add_cpp_int(2.5, 1.1) # Call in *R*