[Rcpp-devel] Issue with Matrices and Iterators
Romain Francois
romain at r-enthusiasts.com
Mon Oct 14 21:41:32 CEST 2013
Le 14/10/13 21:21, Alessandro Mammana a écrit :
> Hi all,
> I have very little experience with Rcpp and also with c++, so I am
> sorry if my question might be too stupid.
> I am trying to use iterators in my code, because I understand them
> better than vectors, because they should be efficient, and because I
> should be able to combine different implementations of vector and
> matrix classes. However the following code does not compile:
>
> #include <Rcpp.h>
> using namespace Rcpp;
>
> typedef NumericVector::iterator DoubleIter;
>
> double sum(DoubleIter b, DoubleIter e){
> double sum = 0;
> while (b!=e){
> sum += *(b++);
> }
> return sum;
> }
>
> // [[Rcpp::export]]
> double sumFirstRow(NumericMatrix mat){
> return sum(mat(0,_).begin(), mat(0,_).end());
> }
>
> The error message is not very useful (or at least I cannot interpret it):
>
> In function 'double sumFirstRow(Rcpp::NumericMatrix)':
> error: no matching function for call to
> 'sum(Rcpp::MatrixRow<14>::iterator, Rcpp::MatrixRow<14>::iterator)'
> note: candidates are:
> note: double sum(DoubleIter, DoubleIter)
> note: no known conversion for argument 1 from
> 'Rcpp::MatrixRow<14>::iterator' to 'DoubleIter {aka double*}'
>
> Am I missing something very basic?
> Thanks a lot!
> Ale
mat(0,_).begin() gives you an object that acts as an iterator over the
first row. This is not the same thing as an iterator over a vector.
> demangle( "NumericVector::iterator" )
[1] "double*"
> demangle( "NumericMatrix::Row::iterator" )
[1] "Rcpp::MatrixRow<14>::iterator"
The first part of what you are missing is templates: you should define
you sum function like this:
template <typename Iterator>
double sum(Iterator b, Iterator e){
double sum = 0;
while (b!=e){
sum += *(b++);
}
return sum;
}
although, this is not generic enough, in situations where you iterate
over the first row of an integer matrix, you should not use double, but
int. So you can do something like this:
template <typename Iterator>
typename traits::remove_reference< typename
std::iterator_traits<Iterator>::value_type>::type sum(Iterator b,
Iterator e){
typedef typename traits::remove_reference<typename
std::iterator_traits<Iterator>::value_type>::type STORAGE ;
STORAGE sum = 0;
while (b!=e) sum += *(b++);
return sum;
}
A bit more involved, but more generic.
Lastly, you can also recognize that this is in fact an algorithm from
the STL: accumulate, so you can do something like this;
// [[Rcpp::export]]
double sumFirstRowSTL(NumericMatrix mat){
return std::accumulate(mat(0,_).begin(), mat(0,_).end(), 0.0);
}
Romain
--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
More information about the Rcpp-devel
mailing list