Reputation: 57
With Rcpp, I've defined a matrix M in C++. Using M.nrow()
, we should be able to retrieve the number of rows. However, when I tried to return the number of rows as an IntegerVector
, the answer is incorrect:
set.seed(1100)
M = matrix(sample(18), nrow = 6)
Rcpp::cppFunction('IntegerVector tccp5(IntegerMatrix M) { int x = M.nrow(); return x;}')
tccp5(M)
# [1] 0 0 0 0 0 0
The correct answer should be the number of rows, e.g.
# [1] 6
Can you please explain what is happening?
Upvotes: 3
Views: 610
Reputation: 20746
While @gfgm's answer is spot on, I wanted to expand upon why declaring as an int
and not IntegerVector
leads to the right construction...
In particular, each return into R is seamlessly converted using wrap()
to an SEXP
, or an S expression that points to the structure. By supplying IntegerVector
and returning an int
, the wrap()
must instantiate a new IntegerVector
of length x
as there is no SEXP
underlying an int
. On the other hand, when the defined return type is int
, the wrap()
feature of Rcpp is able to correctly coerce the int
into an IntegerVector
.
To emphasize the underlying "seamless" transition that happens, let's add the parameter verbose = TRUE
to cppFunction()
to view how the C++ code is: compiled, linked, and imported into R. (Note: I've truncated the output to the compilations.)
If we consider:
Rcpp::cppFunction('IntegerVector tccp5(IntegerMatrix M) { int x = M.nrow(); return x;}',
verbose = TRUE)
We get:
Generated code for function definition:
--------------------------------------------------------
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector tccp5(IntegerMatrix M) { int x = M.nrow(); return x;}
Generated extern "C" functions
--------------------------------------------------------
#include <Rcpp.h>
// tccp5
IntegerVector tccp5(IntegerMatrix M);
RcppExport SEXP sourceCpp_7_tccp5(SEXP MSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< IntegerMatrix >::type M(MSEXP);
rcpp_result_gen = Rcpp::wrap(tccp5(M));
return rcpp_result_gen;
END_RCPP
}
Compared to:
Rcpp::cppFunction('int tccp5(IntegerMatrix M) { int x = M.nrow(); return x;}',
verbose = TRUE)
which gives:
Generated code for function definition:
--------------------------------------------------------
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
int tccp5(IntegerMatrix M) { int x = M.nrow(); return x;}
Generated extern "C" functions
--------------------------------------------------------
#include <Rcpp.h>
// tccp5
int tccp5(IntegerMatrix M);
RcppExport SEXP sourceCpp_9_tccp5(SEXP MSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< IntegerMatrix >::type M(MSEXP);
rcpp_result_gen = Rcpp::wrap(tccp5(M));
return rcpp_result_gen;
END_RCPP
}
Upvotes: 3
Reputation: 3647
The anomalous output arises because of the type declaration of the function.
library(Rcpp)
M <- matrix(sample(1:18), nrow=6)
cppFunction('int tccp6(IntegerMatrix M) { int x = M.nrow(); return x;}')
tccp6(M)
#> [1] 6
Created on 2018-03-22 by the reprex package (v0.2.0).
Upvotes: 1