Rcpp :: rmultinom,带有指向矩阵子视图的指针

时间:2017-11-20 13:26:06

标签: rcpp armadillo

要从Rcpp中的多项分布进行采样,我们可以这样做:

int n = 100;
int k = 3;
arma::vec probs = {0.4,0.2,0.4}
arma::irowvec c(k);
Rcpp::rmultinom(n, probs.begin(), k, c.begin());

我想知道当C是矩阵时我们是否可以这样做。我试试

int n = 100;
int k = 3;
arma::vec probs = {0.4,0.2,0.4}
# C (arma::mat C) passed by reference to the function
Rcpp::rmultinom(n, probs.begin(), k, C.row(1).begin());

但它会引发错误。有一个简单的方法吗?

我想尝试第二种方法,因为我有一个大矩阵C,我通过引用我的函数传递,然后我想在多项式后更新它的行。

MWE:

#include <RcppArmadillo.h>

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

using namespace Rcpp;
using namespace arma;

void subfunction(const arma::imat& C) {

  int n = 100;
  int k = 3;
  arma::vec probs = {0.4,0.2,0.4};

  rmultinom(n, probs.begin(), k, C.col(1).begin());
}

// [[Rcpp::export]]
arma::imat myfunction(){

  arma::imat C = { {1, 2}, 
                  {3, 4},
                  {5, 6}};
  subfunction(C);
  Rcpp::Rcout << "C: " <<  C << std::endl;

}

错误是:

test_multim.cpp:18:44: error: ‘class arma::subview_col<int>’ 
has no member named ‘begin’
rmultinom(n, probs.begin(), k, Ct.col(1).begin());

1 个答案:

答案 0 :(得分:2)

这个问题有两个问题:

  1. rmultinom函数定义所需的类型。
  2. 访问armadillo矩阵的内存指针。
  3. 首先,请注意其中一个错误是:

    mondayso.cpp:16:3: error: no matching function for call to 'Rf_rmultinom'
      rmultinom(1, probs.begin(), k, C.colptr(1));
      ^~~~~~~~~
    /Library/Frameworks/R.framework/Resources/include/Rmath.h:468:6: note: candidate function not viable: no known conversion from 'double *' to 'int *' for 4th argument
    void    rmultinom(int, double*, int, int*);
            ^
    1 error generated.
    

    本质上,rmultinorm函数必须在第4个参数上传入一个整数。由于arma::mat默认构造为double,因此矩阵的类型不合适。在这种情况下,C矩阵必须为arma::imat,因为它使用arma::sword或签名的int组件。

    接下来是armadillo matrices is stored in a column-by-column order的数据(有关详细信息,请参阅Wikipedia's entry)。这意味着指针只能由通过.colptr 轻松建立。这解决了出现的第二个错误:

    error: no member named 'begin' in 'arma::subview_row<int>'
      rmultinom(n, probs.begin(), k, C.row(1).begin());
                                     ~~~~~~~~ ^
    1 error generated.
    

    话虽如此,我已经构建了一个促进转换的例子。

    #include <RcppArmadillo.h>
    
    // [[Rcpp::depends(RcppArmadillo)]]
    
    // [[Rcpp::plugins(cpp11)]]
    
    // [[Rcpp::export]]
    arma::imat test() {
    
      int n = 100;
      int k = 3;
      arma::vec probs = {0.4,0.2,0.4};
    
      arma::imat C = { {1, 3, 5},
                      {2, 4, 6} };
    
      arma::imat Ct = C.t();
    
      // C++ indices start at 0 (thus, this is the second column!)
      rmultinom(n, probs.begin(), k, Ct.colptr(1));
    
      return Ct;
    }
    

    测试

    set.seed(111)
    test()
    #      [,1] [,2]
    # [1,]    1   43
    # [2,]    3   18
    # [3,]    5   39