Ari B. Friedman
Ari B. Friedman

Reputation: 72731

Adding int with Rcpp::IntegerVectors

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

Answers (1)

Dirk is no longer here
Dirk is no longer here

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

Related Questions