How can I use RcppArmadillo?
sangwon-hyun opened this issue · 3 comments
I see from templates that when I'm looking to use Rcpp, I can use this at the beginning of an Rcpp code block:
#include <Rcpp.h>
using namespace Rcpp;
What should I do when I'm looking to use libraries like Armadillo or Eigen (or numeric)? My guess would be to do:
#include <numeric>
#include <RcppArmadillo.h>
#include <RcppEigen.h>
#include <Rcpp.h>
using namespace Rcpp;
using namespace arma;
using namespace Eigen;
But that doesn't work :)
Thanks for this comment. c8e0f5e now makes it possible to use RcppArmadillo and adds a template. To get started, you can work from template:
rmarkdown::draft("create-witharmadillo.Rmd",
template = "make-an-r-package-with-armadillo",
package = "litr")
litr::render("create-witharmadillo.Rmd")
(First, install the latest development version of litr
.)
Ok thank you!
I'm happy to report that I'm able to use not only RcppArmadillo but also RcppEigen! Like this:
// [[Rcpp::depends(RcppArmadillo)]] // [[Rcpp::depends(RcppEigen)]] #include <RcppArmadillo.h> #include <RcppEigen.h> #include <numeric> using namespace arma; using namespace Eigen; using Eigen::Map; // 'maps' rather than copies using Eigen::MatrixXd; // variable size matrix, double precision //' Solve "barebones" sylvester equation that takes upper triangular matrices as coefficients. //' //' @param TA Upper-triangular matrix //' @param TB Upper-triangular matrix //' @param C matrix //' @export // [[Rcpp::export]] Eigen::MatrixXd matrix_function_solve_triangular_sylvester_barebonesC2(const Eigen::MatrixXd & TA, const Eigen::MatrixXd & TB, const Eigen::MatrixXd & C){ // Eigen::eigen_assert(TA.rows() == TA.cols()); // Eigen::eigen_assert(TA.Eigen::isUpperTriangular()); // Eigen::eigen_assert(TB.rows() == TB.cols()); // Eigen::eigen_assert(TB.Eigen::isUpperTriangular()); // Eigen::eigen_assert(C.rows() == TA.rows()); // Eigen::eigen_assert(C.cols() == TB.rows()); // typedef typename MatrixType::Index Index; // typedef typename MatrixType::Scalar Scalar; int m = TA.rows(); int n = TB.rows(); Eigen::MatrixXd X(m, n); for (int i = m - 1; i >= 0; --i) { for (int j = 0; j < n; ++j) { // Compute T_A X = \sum_{k=i+1}^m T_A_{ik} X_{kj} double TAX; if (i == m - 1) { TAX = 0; } else { MatrixXd TAXmatrix = TA.row(i).tail(m-1-i) * X.col(j).tail(m-1-i); TAX = TAXmatrix(0,0); } // Compute X T_B = \sum_{k=1}^{j-1} X_{ik} T_B_{kj} double XTB; if (j == 0) { XTB = 0; } else { MatrixXd XTBmatrix = X.row(i).head(j) * TB.col(j).head(j); XTB = XTBmatrix(0,0); } X(i,j) = (C(i,j) - TAX - XTB) / (TA(i,i) + TB(j,j)); } } return X; }
works well! Here's some test code:
library(tidyverse) set.seed(100) A = runif(4) %>% matrix(ncol=2) B = runif(4) %>% matrix(ncol=2) C = runif(4) %>% matrix(ncol=2) A[lower.tri(A)]=0 B[lower.tri(B)]=0 C[lower.tri(C)]=0 a <- matrix_function_solve_triangular_sylvester_barebonesC2(A, B, C) a
I have another simple request! It seems like litr::document()
is meant to be run at the end of any workflow. However, the current website showcasing the bookdown template doesn't make this clear:
and just ends with "etc." instead of showing 5conclude.Rmd
.
(To elaborate, my workflow was to (1) run litr::render("index.Rmd")
to create a package in ./mypackage
, then (2) run install.package("mypackage", repos=NULL, type="source")
. All without litr::document()
. As I started to define Rcpp functions, I'd get the following error during this second step:
which, it turns out, litr::document() already anticipates! But the above error message by install.packages()
is not useful for your average litr+bookdown user..)
Here's one simple suggestion: when showcasing templates, instead of ending with "etc.", maybe end with 5conclude.Rmd
? Something like this:
index.Rmd, 1description.Rmd, ⋯, 5conclude.Rmd
Or an alternative is to showcase somewhere that the workflow is incomplete if you don't end with litr::document()
. Maybe in the FAQ, or at the end of basic-example.html ?