brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
add-rcpp-integrationAdd Rcpp or RcppArmadillo integration to an R package for high-performance C++ code. Covers setup, writing C++ functions, RcppExports generation, testing compiled code, and debugging. Use when an R function is too slow and profiling confirms a bottleneck, when you need to interface with existing C/C++ libraries, or when implementing algorithms (loops, recur…
Independent GitHub snapshot · Automated classification · Original documentation governs
Integrate C++ into R pkg via Rcpp → perf-critical ops.
usethis::use_rcpp()
Does:
src/ dirRcpp → LinkingTo + Imports in DESCRIPTIONR/packagename-package.R w/ @useDynLib + @importFrom Rcpp sourceCpp.gitignore for compiledRcppArmadillo:
usethis::use_rcpp_armadillo()
→ src/ created, DESCRIPTION updated Rcpp LinkingTo + Imports, R/packagename-package.R has @useDynLib.
If err: usethis::use_rcpp() fails → manually create src/, add LinkingTo: Rcpp + Imports: Rcpp, add #' @useDynLib packagename, .registration = TRUE + #' @importFrom Rcpp sourceCpp to pkg doc file.
Create src/my_function.cpp:
#include <Rcpp.h>
using namespace Rcpp;
//' Compute cumulative sum efficiently
//'
//' @param x A numeric vector
//' @return A numeric vector of cumulative sums
//' @export
// [[Rcpp::export]]
NumericVector cumsum_cpp(NumericVector x) {
int n = x.size();
NumericVector out(n);
out[0] = x[0];
for (int i = 1; i < n; i++) {
out[i] = out[i - 1] + x[i];
}
return out;
}
RcppArmadillo:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
//' Matrix multiplication using Armadillo
//'
//' @param A A numeric matrix
//' @param B A numeric matrix
//' @return The matrix product A * B
//' @export
// [[Rcpp::export]]
arma::mat mat_mult(const arma::mat& A, const arma::mat& B) {
return A * B;
}
→ C++ src at src/my_function.cpp w/ valid // [[Rcpp::export]] + roxygen //' docs.
If err: Verify #include <Rcpp.h> (or <RcppArmadillo.h>), export annotation own line directly above signature, return types map valid Rcpp.
Rcpp::compileAttributes()
devtools::document()
→ R/RcppExports.R + src/RcppExports.cpp auto-generated.
If err: Check C++ syntax. Ensure // [[Rcpp::export]] above each exported fn.
devtools::load_all()
→ Pkg compiles + loads no err.
If err: Check compiler out. Common:
Rcpp::depends for RcppArmadillotest_that("cumsum_cpp matches base R", {
x <- c(1, 2, 3, 4, 5)
expect_equal(cumsum_cpp(x), cumsum(x))
})
test_that("cumsum_cpp handles edge cases", {
expect_equal(cumsum_cpp(numeric(0)), numeric(0))
expect_equal(cumsum_cpp(c(NA_real_, 1)), c(NA_real_, NA_real_))
})
→ Tests pass → C++ identical to R + edge cases (empty, NA) correct.
If err: NA fail → add explicit NA checks via NumericVector::is_na(). Empty fail → guard clause zero-length at top.
Create src/Makevars:
PKG_CXXFLAGS = -O2
Create cleanup in pkg root (CRAN):
#!/bin/sh
rm -f src/*.o src/*.so src/*.dll
Make executable: chmod +x cleanup
→ src/Makevars sets compiler flags, cleanup removes objects. Both at pkg root.
If err: Verify cleanup has exec perms (chmod +x cleanup), Makevars tabs (not spaces) for Makefile rules.
Handle compiled artifacts:
^src/.*\.o$
^src/.*\.so$
^src/.*\.dll$
→ .Rbuildignore patterns prevent compiled objects in tarball, preserve src + Makevars.
If err: devtools::check() → NOTEs about unexpected files in src/. Adjust patterns → exclude only .o, .so, .dll.
devtools::load_all() compiles no warnR CMD check passes no compile warncompileAttributes(): Must regen RcppExports after C++ changesdouble not int for large numericsdeleteRcpp::NumericVector::is_na()@useDynLib: Pkg doc must @useDynLib packagename, .registration = TRUEcreate-r-package — pkg setup before Rcppwrite-testthat-tests — testing compiled fnssetup-github-actions-ci — CI needs C++ toolchainsubmit-to-cran — compiled pkgs need extra CRAN checks