Converting Eigen::MatrixXd to arma::mat and make a copy on a new object

时光毁灭记忆、已成空白 提交于 2019-12-12 22:44:33

问题


I have a function within which I want to convert an Eigen::MatrixXd object to arma::mat.

I am aware of this question but I can't seem to be able to correct the behavior that I'm getting. Calling matrixxd_to_armamat from R would cause no issues, the problem is when I have this conversion in another function in C. This is a little confusing and I would like to understand what's going on.

#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
*/


回答1:


So, after running this, I can only produce a problem with A_arma object creation. The object here is getting an odd value indicating that the memory mapping was bad. My thought on this is because it is being copied into the function instead of a reference update. The original answer showed the manipulation under a scoped function that allowed the reference and memory re-use.

In particular, from the armadillo docs on advanced ctors:

Create a matrix using data from writable auxiliary (external) memory, where ptr_aux_mem is a pointer to the memory. By default the matrix allocates its own memory and copies data from the auxiliary memory (for safety). However, if copy_aux_mem is set to false, the matrix will instead directly use the auxiliary memory (ie. no copying); this is faster, but can be dangerous unless you know what you are doing!

The latter part is my emphasis.

So, here under a pass-by-copy paradigm, the object needs to be fully copied vs. a reference update if writing a common cast function.

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;
}

Now, if you are okay with linking back to the original Eigen object through a reference, then this should work:

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;
}

Running both yields:

tester()
# 1 -1
# 2 -2
#   1.0000  -1.0000
#   2.0000  -2.0000
#
#   1.0000  -1.0000
#   2.0000  -2.0000
#
#     [,1] [,2]
#[1,]    1   -1
#[2,]    2   -2


来源:https://stackoverflow.com/questions/58176022/converting-eigenmatrixxd-to-armamat-and-make-a-copy-on-a-new-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!