我有以下代码:
#include <RcppEigen.h>
using namespace Rcpp;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using Eigen::Lower;
using Eigen::Map;
// fills passed dense objects with unit normal random variables
template <typename Derived>
void fillUnitNormal(Eigen::DenseBase<Derived>& Z){
int m = Z.rows();
int n = Z.cols();
NumericVector r(m*n);
r = rnorm(m*n, 0, 1); // using vectorization from Rcpp sugar
Map<VectorXd> rvec(as<Map<VectorXd> >(r));
Map<MatrixXd> rmat(rvec.data(), m, n);
Z = rmat;
}
那一段时间对我来说一直很好。但是,我意识到,如果Z是VectorXd对象,则该函数将失败。用法线(0,1)绘制填充从Eigen :: DenseBase类继承的Eigen对象的每个元素的正确方法是什么?
答案 0 :(得分:2)
一种方法是将std::copy
的随机值变成Z
。由于Eigen
不支持std::begin()
,因此我决定使用.data()
提供的原始指针。但是,这在Eigen::DenseBase
级别不可用。尽管在Eigen::PlainObjectBase
的{{3}}中有两个级别,但它起作用:
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
// fills passed dense objects with unit normal random variables
template <typename T>
void fillUnitNormal(Eigen::PlainObjectBase<T>& Z){
int m = Z.rows();
int n = Z.cols();
Rcpp::NumericVector r(m*n);
r = Rcpp::rnorm(m*n, 0, 1); // using vectorization from Rcpp sugar
std::copy(std::begin(r), std::end(r), Z.data());
}
// [[Rcpp::export]]
Rcpp::List test(int n) {
Eigen::MatrixXd mat(n, n);
Eigen::VectorXd vec(n);
fillUnitNormal(mat);
fillUnitNormal(vec);
// gives compile time error: fillUnitNormal(Rcpp::NumericVector::create(n));
return Rcpp::List::create(mat, vec);
}
/*** R
test(5)
*/