Rcpp中的if-else语句出现问题

Troubles in if-else statement in Rcpp

本文关键字:问题 语句 中的 if-else Rcpp      更新时间:2023-10-16

使用以下简化代码,我希望从N(0,1)分布进行模拟,并返回一个包含模拟值的列表以及一个取决于模拟法线的向量(请参阅下面的代码)。问题是if-else语句根本不起作用!拜托,有人能帮我弄清楚问题出在哪里吗?

#include <RcppArmadillo.h>
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::depends(RcppArmadillo)]]
//[[Rcpp::export]]
List cond(arma::vec epsilon, IntegerVector Nsim) {
int iNsim = Nsim[0];
arma::vec ans(1);
arma::vec epsil(epsilon);
arma::vec vans  = arma::zeros(iNsim);
arma::vec vcond = arma::zeros(iNsim);
LogicalVector cond;
RNGScope scope;
for (int i=0; i<iNsim; i++) {
ans = Rcpp::rnorm(1, 0.0, 1.0);
vans.row(i) = ans[0];
cond = abs(ans) >= epsil;
if (cond) {
vcond.row(i) = 10;
} else {
vcond.row(i) = -10;
}
}
return List::create(
_["sim"] = vans,
_["cond"] = vcond);  
}

我在R中运行它,方法是将它保存到file.cpp,然后通过sourceCpp("file.cpp").

原始代码混淆了在哪里使用矢量和在哪里使用标量。

他是较短和修复版本:

#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::export]]
DataFrame cond(double epsil, int iNsim) {
double ans;
NumericVector vans(iNsim);
NumericVector vcond(iNsim);
RNGScope scope;
for (int i=0; i<iNsim; i++) {
ans = R::rnorm(0.0, 1.0);
vans[i] = ans;
if (fabs(ans) >= epsil) {
vcond[i] = 10;
} else {
vcond[i] = -10;
}
}
return DataFrame::create(_["sim"] = vans,
_["cond"] = vcond);  
}

除了在使用标量的地方使用(和传递)标量外,它还将abs()更正为fabs()——这是一个常见的C/C++问题。我还恢复了Rcpp矢量——尽管我喜欢使用Armadillo,但这里不需要它。

以下是给定随机种子的示例输出:

R> sourceCpp("/tmp/erlis.cpp")
R> set.seed(1)
R> cond(1.0, 6)   
sim cond              
1 -0.626454  -10
2  0.183643  -10
3 -0.835629  -10 
4  1.595281   10
5  0.329508  -10
6 -0.820468  -10
R> 

以下是解决方案:

#include <RcppArmadillo.h>
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::depends(RcppArmadillo)]]
//[[Rcpp::export]]
List cond(arma::vec epsilon, IntegerVector Nsim) {
int iNsim = Nsim[0];
arma::vec ans(1);
arma::vec epsil(epsilon);
arma::vec vans  = arma::zeros(iNsim);
arma::vec vcond = arma::zeros(iNsim);
LogicalVector cond;
RNGScope scope;
for (int i=0; i<iNsim; i++) {
ans = Rcpp::rnorm(1, 0.0, 1.0);
vans.row(i) = ans[0];
bool go_ = true;
for(int i = 0; i < ans.size(); i++)
if(abs(ans[i]) < epsil[0])
go_ = false;
if (go_) {
vcond.row(i) = 10;
} else {
vcond.row(i) = -10;
}
}
return List::create(
_["sim"] = vans,
_["cond"] = vcond);  
}