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
.
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.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'
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.