将BigMatrix /数组转换为Armadillo矩阵

时间:2014-07-24 12:33:55

标签: c++ rcpp armadillo

我有一个big.matrix我想要转换为arma::Mat,以便我可以使用Armadillo的线性代数功能。

然而,我似乎无法让演员工作。

据我可以从阅读中收集,两者都在内部以列主格式存储,而big.matrix的实际矩阵组件只是<T>类型的指针(char / short / int / double

以下代码编译,但是对arma::Mat的强制转换不起作用,在遍历转换矩阵时进行segfaulting。

#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::depends(BH, bigmemory, RcppArmadillo)]]
#include <bigmemory/BigMatrix.h>

template <typename T>
void armacast(const arma::Mat<T>& M) {
  // This segfaults
  for (int j = 0; j < 2; j++) {
    for (int i = 0; i < 2; i++) {
      std::cout << M.at(j, i) << std::endl;
    }   
  }
  std::cout << "Success!" << std::endl;                                                                                                                                                                                                       
}

// [[Rcpp::export]]
void armacast(SEXP pDat) {
  XPtr<BigMatrix> xpDat(pDat);

  if (xpDat->matrix_type() == 8) {
    // I can iterate over this *mat and get sensible output.
    double *mat = (double *)xpDat->matrix();
    for (int j = 0; j < 2; j++) {
      for (int i = 0; i < 2; i++) {
        std::cout << *mat + 2 * (j + 0) + i << std::endl;
      }   
    }
    armacast((const arma::Mat<double> &)mat);
  } else {
    std::cout << "Not implemented yet!" << std::endl;
  }
}

在R:

library(Rcpp)
library(RcppArmadillo)
library(bigmemory)
sourceCpp("armacast.cpp")
m <- as.big.matrix(matrix(1:4, 2), type="double")
armacast(m@address)

1 个答案:

答案 0 :(得分:4)

好问题!我们可以将其转换为另一个Rcpp Gallery帖子。

您可能已经掩盖了一个重要的细节。 Bigmemory对象是外部,因此我们得到R不让其内存管理干扰。 Armadillo确实有这方面的构造函数(请在那里阅读文档和警告),所以在第一个实例中 我们可以做到

arma::mat M( (double*) xpDat->matrix(), xpDat->nrow(), xpDat->ncol(), false);

我们使用指向矩阵数据的指针,以及行和列计数。完整版:

// [[Rcpp::export]]
void armacast(SEXP pDat) {
  XPtr<BigMatrix> xpDat(pDat);

  if (xpDat->matrix_type() == 8) {
    arma::mat M(mat, xpDat->nrow(), xpDat>-ncol(), false);
    M.print("Arma matrix M");
  } else {
    std::cout << "Not implemented yet!" << std::endl;
  }
}

它正确地调用了犰狳的打印方法:

R> armacast(m@address)
Arma matrix M
   1.0000   3.0000
   2.0000   4.0000
R>