This works with RcppEigen 3.3.x. We can talk about generalizing it for rstanarm at the meeting.
X <- rbind(
c(0, 3, 0, 0, 0),
c(22, 0, 0, 0, 17),
c(7, 5, 0, 1, 0),
c(0, 0, 0, 0, 0),
c(0, 0, 14, 0, 8)
)
x <- c(X)
x <- x[x != 0]
InnerIndices <- c(1L, 2L, 0L, 2L, 4L, 2L, 1L, 4L)
OuterStarts <- c(0L, 2L, 4L, 5L, 6L, 8L)
beta <- rnorm(nrow(X))
Rcpp::sourceCpp('sparse.cpp')
args(smv)
cbind(R = X %*% beta, Eigen =
smv(rows = nrow(X), cols = ncol(X), Values = x,
InnerIndices = InnerIndices, OuterStarts = OuterStarts,
InnerNNZs = length(x), beta = beta) )
where sparse.cpp is a file that contains
#include <Rcpp.h>
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
Eigen::VectorXd
smv(int rows, int cols,
std::vector<double> Values, std::vector<int> InnerIndices, std::vector<int> OuterStarts,
int InnerNNZs, Eigen::VectorXd beta) {
const Eigen::Index r = rows;
const Eigen::Index c = cols;
const Eigen::Index nnz = InnerNNZs;
double* Values_ptr = &Values[0];
typedef Eigen::SparseMatrix<double>::StorageIndex StorageIndex;
StorageIndex* OS_ptr = &OuterStarts[0];
StorageIndex* II_ptr = &InnerIndices[0];
Eigen::Map<const Eigen::SparseMatrix<double> >
sm1(r, c, nnz, OS_ptr, II_ptr, Values_ptr);
return sm1 * beta;
}