我遇到了一些我无法解决的问题。这是更大编码工作的一部分,但最小的例子是:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
Rcpp::List foo(arma::vec & tau2, const arma::vec & nu) {
arma::vec bet = Rcpp::rnorm(3);
tau2 = R::rgamma(1, arma::as_scalar(sum(pow(bet, 2)/nu)));
return Rcpp::List::create(Rcpp::Named("nu") = nu,
Rcpp::Named("tau2") = tau2);
}
(tau2
,虽然是标量,但这里是一个向量,因为我想通过引用传递:function pass by reference in RcppArmadillo)
让我感到困惑的是,如果我现在运行以下R代码:
n <- 3
m <- matrix(0, n, 1)
for (r in 1:1000) {
tau2 <- 1.0
nu <- matrix(1, n, 1)
upd <- foo(tau2, nu)
}
我明白了:
error: element-wise division: incompatible matrix dimensions: 3x1 and 18x1
Error in foo(tau2, nu) :
element-wise division: incompatible matrix dimensions: 3x1 and 18x1
18x1
变化的地方;主要是0x1
,但它始终是3
的倍数。
查看输出:
> nu
[,1] [,2] [,3] [,4]
[1,] 4.165242 4.165242 4.165242 4.165242
[2,] 4.165242 4.165242 4.165242 4.165242
[3,] 4.165242 4.165242 4.165242 4.165242
> upd
$nu
[,1]
[1,] 1
[2,] 1
[3,] 1
$tau2
[,1]
[1,] 4.165242
也就是说,尽管将nu
声明为常量引用(我这样做是因为我不希望它更改),但它会被更改。填充的值是upd$tau2
(但为什么?)。
奇怪的是,我可以通过看似无意义的改变来消除这种行为:
tau2 <- 1.0
或nu <- matrix(1, n, 1)
(或两者)放在循环之外arma::vec tau2
)pow(bet, 2)
除以nu
nu <- rep(1, n)
也许最令人困惑的部分是,如果我在循环中选择代码块并重复运行它,它就可以工作(!)。但是,如果我使用循环运行R代码,它会在第二次迭代时崩溃。
因为我似乎能够解决问题,所以我最感兴趣的是学习这里发生的事情。我怀疑这只是因为我缺乏C ++方面的专业知识和各种变量类型的鲁莽,所以知道造成这一切的原因是非常有价值的。
答案 0 :(得分:2)
两个修正:
tau2
是双人(模仿@dirkeddelbuettel)NumericVector
之前生成bet
长度 n 的临时变量代码:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
Rcpp::List foo(double tau2, const arma::vec & nu) {
int n = nu.n_elem;
Rcpp::NumericVector x = Rcpp::rnorm(n);
arma::vec bet = arma::vec(x.begin(), n, true, false);
tau2 = R::rgamma(1, arma::as_scalar(sum(pow(bet, 2) / nu)));
return Rcpp::List::create(Rcpp::Named("nu") = nu,
Rcpp::Named("tau2") = tau2);
}
测试用例:
n <- 3
m <- matrix(0, n, 1)
for (r in 1:1000) {
tau2 <- 1.0
nu <- matrix(1, n, 1)
upd <- foo(tau2, nu)
}
upd
#> $nu
#> [,1]
#> [1,] 1
#> [2,] 1
#> [3,] 1
#>
#> $tau2
#> [1] 3.292889
答案 1 :(得分:1)
如果我将界面更改为使用double
,则一切正常:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
Rcpp::List foo(double & tau2, const arma::vec & nu) {
arma::vec bet = Rcpp::rnorm(3);
tau2 = R::rgamma(1, arma::as_scalar(sum(pow(bet, 2)/nu)));
return Rcpp::List::create(Rcpp::Named("nu") = nu,
Rcpp::Named("tau2") = tau2);
}
/*** R
n <- 3
m <- matrix(0, n, 1)
for (r in 1:1000) {
tau2 <- 1.0
nu <- matrix(1, n, 1)
upd <- foo(tau2, nu)
}
*/
R> sourceCpp("/tmp/hejseb.cpp")
R> n <- 3
R> m <- matrix(0, n, 1)
R> for (r in 1:1000) {
+ tau2 <- 1.0
+ nu <- matrix(1, n, 1)
+ upd <- foo(tau2, nu)
+ }
R> upd
$nu
[,1]
[1,] 1
[2,] 1
[3,] 1
$tau2
[1] 1.77314
R>
我不确定这些是你预期的数字。我没有时间研究你想要做的事情。