Reputation: 72731
Here's a reproducible example of a problem I've experienced in various contexts. Basically I have a C++ int
and an Rcpp IntegerVector
and I'd like to just add one integer to another and store it into a new IntegerVector
. The same problem happens with numeric types, but let's keep it to integers for now.
library(inline)
set.seed(123)
x <- sample(1:100,5)
cpp_src <- '
Rcpp::IntegerVector xa = clone(x);
Rcpp::IntegerVector sa(s);
int currentSum = 12;
std::cout << sa[0] << " ";
std::cout << currentSum << " ";
Rcpp::IntegerVector remainingQuantity = sa[0] - currentSum;
std::cout << remainingQuantity << "\\n";
return remainingQuantity;
'
sumto <- cxxfunction( signature(x="integer", s="integer"), body=cpp_src, plugin="Rcpp", verbose=TRUE )
testresult <- sumto(x=x, s=100L)
And here are the (disastrous!) results:
> testresult <- sumto(x=x, s=100L)
100 12 0x50ebf50
> x
[1] 29 79 41 86 91
> testresult
[1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[63] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
> length(testresult)
[1] 88
I suspect that at the root of the problem is that I am a C++ newb and simply don't have a good mental model for anything much beyond C variable types (i.e. I understand pointers, references, and dereferencing at a functional level, but I have no idea why dereferencing an IntegerVector
seems to work in some places but not in others, or what data type std::accumulate
returns, etc.).
At any rate, if someone could give me an idiom for how to add int
to Rcpp::IntegerVectors
, it would be appreciated. Even more helpful would be if you could explain why whatever solution you posted works.
Upvotes: 2
Views: 1808
Reputation: 368221
I will admit that I am not entirely sure what your example is meant to do, but here is a variant, using Armadillo types. I kept your input vector, and also show it in stdout
.
cpp_src <- '
arma::ivec sa = Rcpp::as<arma::ivec>(x);
Rcpp::Rcout << sa << std::endl;
int currentSum = 12;
Rcpp::Rcout << sa[0] << " ";
Rcpp::Rcout << currentSum << " ";
int remainingQuantity = arma::as_scalar(sa[0]) - currentSum;
Rcpp::Rcout << remainingQuantity << std::endl;
return Rcpp::wrap(remainingQuantity);
'
armasumto <- cxxfunction(signature(x="numeric", s="integer"),
body=cpp_src, plugin="RcppArmadillo", verbose=FALSE )
testresult <- armasumto(x=x, s=100L)
With that, I get:
R> cpp_src <- '
+ arma::ivec sa = Rcpp::as<arma::ivec>(x);
+ Rcpp::Rcout << sa << std::endl;
+ int currentSum = 12;
+ Rcpp::Rcout << sa[0] << " ";
+ Rcpp::Rcout << currentSum << " ";
+ int remainingQuantity = arma::as_scalar(sa[0]) - currentSum;
+ Rcpp::Rcout << remainingQuantity << std::endl;
+ return Rcpp::wrap(remainingQuantity);
+ '
R>
R> armasumto <- cxxfunction(signature(x="numeric", s="integer"),
+ body=cpp_src, plugin="RcppArmadillo", verbose=FALSE )
R> testresult <- armasumto(x=x, s=100L)
29
79
41
86
91
29 12 17
R>
And for completeness, now that we established that everything is on scalars, the same with Rcpp vectors:
R> cpp_src <- '
+ Rcpp::IntegerVector xa(x);
+ int currentSum = 12;
+ Rcpp::Rcout << xa[0] << " ";
+ Rcpp::Rcout << currentSum << " ";
+ int remainingQuantity = xa[0] - currentSum;
+ Rcpp::Rcout << remainingQuantity << std::endl;
+ return Rcpp::wrap(remainingQuantity);
+ '
R> newsumto <- cxxfunction(signature(x="integer", s="integer"),
+ body=cpp_src, plugin="Rcpp" )
R> testresult <- newsumto(x=x, s=100L)
29 12 17
R>
Upvotes: 4