Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Rcpp::Rcout output stream device. Based on a contributed
Rcpp patch by Jelper Ypma, the
Rcpp::Rcout output stream gets redirected to R’s buffered output. In other words, R’s own output and that
eminating from C++ code using Rcpp::Rcout are now both in sync. This avoids a stern warning
from Section 5.6 in the Writing R Extensions manual:
Using C++ iostreams, as in this example, is best avoided. There is no guarantee that the output will appear in the R console, and indeed it will not on the R for Windows console. Use R code or the C entry points (*note Printing) for all I/O if at all possible.and does in fact provide exactly what is recommended: the same entry points R itself uses.
Below is a sample program, once again using the wonderful inline
package to compile, load and link C++ code into R from a simple text variable submitted to the cxxfunction.
What is shown in R code to load the package, the definition of the C++ code as assigned to a variable src
and the creation of the dynamically-loadaded R function called fun which contains the code from we
compiled, link and load via a single call to cxxfunction() given src.
library
library(inline)
src <- '
Rcpp::Rcout << "Armadillo version: " << arma::arma_version::as_string() << std::endl;
// directly specify the matrix size (elements are uninitialised)
arma::mat A(2,3);
// .n_rows = number of rows (read only)
// .n_cols = number of columns (read only)
Rcpp::Rcout << "A.n_rows = " << A.n_rows << std::endl;
Rcpp::Rcout << "A.n_cols = " << A.n_cols << std::endl;
// directly access an element (indexing starts at 0)
A(1,2) = 456.0;
A.print("A:");
// scalars are treated as a 1x1 matrix,
// hence the code below will set A to have a size of 1x1
A = 5.0;
A.print("A:");
// if you want a matrix with all elements set to a particular value
// the .fill() member function can be used
A.set_size(3,3);
A.fill(5.0);
A.print("A:");
arma::mat B;
// endr indicates "end of row"
B << 0.555950 << 0.274690 << 0.540605 << 0.798938 << arma::endr
<< 0.108929 << 0.830123 << 0.891726 << 0.895283 << arma::endr
<< 0.948014 << 0.973234 << 0.216504 << 0.883152 << arma::endr
<< 0.023787 << 0.675382 << 0.231751 << 0.450332 << arma::endr;
// print to the cout stream
// with an optional string before the contents of the matrix
B.print("B:");
// the << operator can also be used to print the matrix
// to an arbitrary stream (cout in this case)
Rcpp::Rcout << "B:" << std::endl << B << std::endl;
// save to disk
B.save("B.txt", arma::raw_ascii);
// load from disk
arma::mat C;
C.load("B.txt");
C += 2.0 * B;
C.print("C:");
// submatrix types:
//
// .submat(first_row, first_column, last_row, last_column)
// .row(row_number)
// .col(column_number)
// .cols(first_column, last_column)
// .rows(first_row, last_row)
Rcpp::Rcout << "C.submat(0,0,3,1) =" << std::endl;
Rcpp::Rcout << C.submat(0,0,3,1) << std::endl;
// generate the identity matrix
arma::mat D = arma::eye<arma::mat>(4,4);
D.submat(0,0,3,1) = C.cols(1,2);
D.print("D:");
// transpose
Rcpp::Rcout << "trans(B) =" << std::endl;
Rcpp::Rcout << trans(B) << std::endl;
// maximum from each column (traverse along rows)
Rcpp::Rcout << "max(B) =" << std::endl;
Rcpp::Rcout << max(B) << std::endl;
// maximum from each row (traverse along columns)
Rcpp::Rcout << "max(B,1) =" << std::endl;
Rcpp::Rcout << max(B,1) << std::endl;
// maximum value in B
Rcpp::Rcout << "max(max(B)) = " << max(max(B)) << std::endl;
// sum of each column (traverse along rows)
Rcpp::Rcout << "sum(B) =" << std::endl;
Rcpp::Rcout << sum(B) << std::endl;
// sum of each row (traverse along columns)
Rcpp::Rcout << "sum(B,1) =" << std::endl;
Rcpp::Rcout << sum(B,1) << std::endl;
// sum of all elements
Rcpp::Rcout << "sum(sum(B)) = " << sum(sum(B)) << std::endl;
Rcpp::Rcout << "accu(B) = " << accu(B) << std::endl;
// trace = sum along diagonal
Rcpp::Rcout << "trace(B) = " << trace(B) << std::endl;
Rcpp::Rcout << std::endl;
'
fun <- cxxfunction(signature(), body=src, plugin="RcppArmadillo")
setwd("/tmp") # adjust on other OSs
fun() # output to stdout
sink("rcpparma.log.txt") # start 'sink' to output to file
fun() # no output to screen
sink() # stop 'sink'
We then switch to a temporary directory (as the example code, taken from one of the two examples in Conrad’s
Armadillo sources, creates a temporary file) and run the new function. To demontrate
how it does in fact now mesh perfectly with R, we create an output ‘sink’ (which catches all output) and re-run.
This simple example demonstrated how we can use the new Rcout output stream from
Rcpp to have dynamically-loaded C++ code cooperate more
cleanly with the (buffered) R output. It also demontrated some of the nice features in Armadillo
which we bring to R via RcppArmadillo.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
