Преобразование Eigen :: MatrixXd в arma :: mat и создание копии нового объекта - PullRequest
1 голос
/ 01 октября 2019

У меня есть функция, внутри которой я хочу преобразовать объект Eigen::MatrixXd в arma::mat.

Мне известен этот вопрос , но я не могу исправить поведение, которое я получаю. Вызов matrixxd_to_armamat из R не вызовет проблем, проблема в том, что у меня есть это преобразование в другой функции в 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
*/

1 Ответ

5 голосов
/ 01 октября 2019

Итак, после этого я могу создать проблему только с созданием объекта A_arma. Объект здесь получает нечетное значение, указывающее, что отображение памяти было плохим. Я думаю об этом, потому что он копируется в функцию вместо справочного обновления. Первоначальный ответ показал манипуляцию в рамках функции с ограничением, которая позволяла повторно использовать ссылку и память.

В частности, из документов armadillo на расширенные ctors :

Создать матрицу, используя данные из записываемой вспомогательной (внешней) памяти, где ptr_aux_mem равноуказатель на память. По умолчанию матрица выделяет собственную память и копирует данные из вспомогательной памяти (для безопасности). Однако, если для copy_aux_mem задано значение false, матрица вместо этого будет напрямую использовать вспомогательную память (т.е. без копирования);это быстрее, но может быть опасно, если вы не знаете, что делаете!

Последняя часть - мой акцент.

Итак, здесь, под прохождениемКопировать парадигму, объект должен быть полностью скопирован против обновления ссылки, если вы пишете общую функцию приведения.

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

Запуск обоих выходов:

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
...