将Eigen :: MatrixXd转换为arma :: mat并在新对象上进行复制

问题描述 投票:0回答:1

我有一个函数,希望将Eigen::MatrixXd对象转换为arma::mat

我知道this question,但似乎无法纠正我得到的行为。从R调用matrixxd_to_armamat不会造成任何问题,问题是当我在C中的另一个函数中进行此转换时。这有点令人困惑,我想了解发生了什么。

#include <RcppArmadillo.h>
#include <RcppEigen.h>

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

using namespace std;

arma::mat matrixxd_to_armamat(Eigen::MatrixXd eigen_A) {
  arma::mat arma_B = arma::mat(eigen_A.data(), eigen_A.rows(), eigen_A.cols(),
                               false, false);
  return arma_B;
}

arma::mat matrixxd_to_armamat2(Eigen::MatrixXd& eigen_A) {
  arma::mat arma_B = arma::mat(eigen_A.data(), eigen_A.rows(), eigen_A.cols(),
                               false, false);
  return arma_B;
}



//[[Rcpp::export]]
arma::mat tester(){
  Eigen::MatrixXd A_eigen(2,2);
  A_eigen(0,0) = 1.0;
  A_eigen(1,0) = 2.0;
  A_eigen(0,1) = -1.0;
  A_eigen(1,1) = -2.0;

  Rcpp::Rcout << A_eigen << endl;

  arma::mat A_arma  = matrixxd_to_armamat(A_eigen);
  arma::mat A_arma2 = matrixxd_to_armamat2(A_eigen);

  Rcpp::Rcout << A_arma << endl;
  Rcpp::Rcout << A_arma2 << endl;

  return A_arma2;
}
/* In R
> tester()
 1 -1
 2 -2
  4.6503e-310  -1.0000e+00
  4.9407e-324   7.2661e-43

   1.0000  -1.0000
   2.0000  -2.0000

              [,1] [,2]
[1,] 4.650273e-310   -1
[2,]  2.000000e+00   -2
*/

c++ eigen rcpp armadillo
1个回答
1
投票

因此,运行此命令后,我只能在创建A_arma对象时出现问题。此处的对象得到一个奇数值,表示内存映射错误。我对此的想法是因为将其复制到函数中而不是引用更新中。原始答案显示了在范围函数下的操作,该功能允许引用和内存的重用。

特别是来自armadillo docs on advanced ctors

使用来自可写辅助(外部)存储器的数据创建矩阵,其中ptr_aux_mem是指向该存储器的指针。默认情况下,矩阵会分配自己的内存并从辅助内存中复制数据(出于安全考虑)。 但是,如果将copy_aux_mem设置为false,则矩阵将直接使用辅助存储器(即,不进行复制);这会更快,但除非您知道自己在做什么,否则可能很危险!

后一部分是我的重点。

因此,在这里,在传递复制范式下,如果编写通用的强制转换函数,则需要完全复制对象,而不是参考更新。

armadillo

现在,如果您可以通过引用链接回原始的arma::mat matrixxd_to_armamat(Eigen::MatrixXd eigen_A) { arma::mat arma_B = arma::mat(eigen_A.data(), eigen_A.rows(), eigen_A.cols(), true, // changed from false to true. false); return arma_B; } 对象,那么应该可以:

Eigen

同时运行两个产量:

arma::mat matrixxd_to_armamat2(Eigen::MatrixXd& eigen_A) {
    arma::mat arma_B = arma::mat(eigen_A.data(), eigen_A.rows(), eigen_A.cols(),
                                 false, false);
    return arma_B;
}
© www.soinside.com 2019 - 2024. All rights reserved.