Ding Li
Ding Li

Reputation: 723

noncontiguous access of Armadillo matrix columns

I have the indices of a matrix stored in a list, and I want to access these columns in Rcpp.

library(Rcpp)
library(RcppArmadillo)
cppFunction('arma::mat tmp(arma::mat mat1, List list1) {
            arma::mat mat2=mat1.row(1);
return mat2.cols(as<arma::uvec>(list1[1]));

            }',depends = "RcppArmadillo")

However, the above function will cause a fatal error ("R sessions Aborted"). e.g.,

tmp(matrix(1:4,2),list(list(c(0))))

A similar function in pure rcpp will return this error.

note: in instantiation of function template specialization 'Rcpp::Vector<19, PreserveStorage>::create<Rcpp::traits::named_object<arma::subview_row<double> >, Rcpp::traits::named_object<arma::subview_elem2<double, arma::Mat<unsigned int>, arma::Mat<unsigned int> > >, Rcpp::traits::named_object<Rcpp::internal::generic_proxy<19, PreserveStorage> > >' requested here

From this documentation, I should be able to access these columns via arma:uvec.

X.cols( vector_of_column_indices )

I'm not sure why it still asks me to use this format X.cols( first_col, last_col ). Any help is greatly appreciated!

Upvotes: 0

Views: 153

Answers (1)

Dirk is no longer here
Dirk is no longer here

Reputation: 368629

The question is not particularly clear (and may benefit from some editing / clarification) but here are some key points:

  • the memory model for R as well as as countless other applications is simple as requires contiguous memory for a vector
  • a matrix is really just a vector with two-dimensional indexing so the same holds: contiguous memory is needed
  • lists in R a different from matrices as they really are a list of columns
  • same for data.frames which are, simplyfying somewhat, subclassed lists

So there are things you can, and cannot do. The Armadillo documentation is good and can help in stacking and combining parts of vectors into larger ones.

Edit: Here is a very simple example that shows how to address this. Because Armadillo clearly wants a matrix to subset from, and a uvec with indices we ... simply give it a matrix and a vector of (unsigned) ints (which RcppArmadillo maps for us). So you main issue really is how you go from the List to the uvec --- which does not work in the form that you have. I would recommend being more explicit in how you create the vector and properly instantiate one.

Code

#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
arma::mat subsetOfMatrix(arma::mat X, arma::uvec v) {
  return X.cols(v);
}

/*** R
M <- matrix(1:16,4,4)
subsetOfMatrix(M, c(0L, 2L))
*/

Output

R> Rcpp::sourceCpp("~/git/stackoverflow/64998018/answer.cpp")

R> M <- matrix(1:16,4,4)

R> subsetOfMatrix(M, c(0L, 2L))
     [,1] [,2]
[1,]    1    9
[2,]    2   10
[3,]    3   11
[4,]    4   12
R> 

Upvotes: 3

Related Questions