[Rcpp-devel] NumericVector

Romain Francois romain at r-enthusiasts.com
Fri Aug 16 18:37:38 CEST 2013


Le 16/08/13 17:59, James Li a écrit :
> Dear Dirk and Rcpp-devel members,

Please be aware that Rcpp is a joint project and has been so for several 
years now.

> I am currently passing a multidimensional (N > 2) array (i.e.
> array(NA, dim = rep(3,5)) ) from R via Rcpp using
>
> "in C++:"
>
> //[[Rcpp::export]]
> Rcpp::List check_arrayC (Rcpp::NumericVector x, Rcpp::IntegerVector modes){
> //do stuff to x
>      return Rcpp::List::create(Rcpp::_["data"] = x, Rcpp::_["modes"] = modes);
> }
>
>
> "in R:"
>
> a <- array(1:32, dim=rep(2,5))
> b <- check_arrayC(a, dim(a))
>
> While I know that a multidimensional array is stored as a contiguous
> array internally, is there currently a more natural/efficient way to
> pass it back and forth within Rcpp?
>
> Also from Dirk's book, it seems that an instance of
> Rcpp::NumericVector can be instantiated into a multidimensional array
> via
>
> Rcpp::NumericVector vec3 =Rcpp::NumericVector( Rcpp::Dimension(4, 5, 6));
>
> In this case, how do we access element vec3[1,2,3]?
>
> Some background about what I am trying to do: I would like to create a
> multidimensional array wrapper class around the base R multi-way array
> class. I would also like to be able to pass this multidimensional
> array via Rcpp to do all the heavy-lifting in c++. Ideally, I could
> also convert the mda into a Boost::multi_array.
>
> Thanks in advance for any help.
>
> -James

We don't have support for this in Rcpp. But is is easy to do it 
yourself, with only a small code addition, e.g. :

#include <Rcpp.h>
using namespace Rcpp ;

class Offset {
private:
     int nrows, ncols, nmats ;

public:
     Offset( int nrows_, int ncols_, int nmats_) : nrows(nrows_), 
ncols(ncols_), nmats(nmats_){}

     int operator()( int i, int j, int k){
         return i + j * nrows + k * ( nrows * ncols ) ;
     }

} ;

// [[Rcpp::export]]
NumericVector foo(){
     NumericVector vec3 = NumericVector( Dimension(4, 5, 6) );
     Offset offset( 4, 5, 6 ) ;

     vec3[ offset(0,0,0) ] = 1.0 ;
     vec3[ offset(1,1,1) ] = 2.0 ;
     return vec3 ;
}

/*** R
     foo()
*/


You could go further and encapsulate both in a dedicated class, e.g. 
Array3 as in this: I have included the needed bits so that you can :
- pass an Array3 from R
- return one to R
- extract or set data using the operator()

It is not full featured, lacks testing, etc ... with it works:

#include <Rcpp.h>
using namespace Rcpp ;

class Offset{
private:
     int nrows, ncols, nmats ;

public:
     Offset( IntegerVector dim ) : nrows(dim[0]), ncols(dim[1]), 
nmats(dim[2]){}

     Offset( int nrows_, int ncols_, int nmats_) : nrows(nrows_), 
ncols(ncols_), nmats(nmats_){}

     int operator()( int i, int j, int k){
         return i + j * nrows + k * ( nrows * ncols ) ;
     }

} ;

class Array3 : public NumericVector {
private:
     Offset offset ;

public:
     Array3( SEXP x) : NumericVector(x), offset( 
(IntegerVector)((RObject)x).attr("dim") ) { }
     Array3( Dimension dim ): NumericVector( dim ), offset( dim[0], 
dim[1], dim[2] ) {}
     Array3( int nrows_, int ncols_, int nmats_ ): NumericVector( 
Dimension(nrows_, ncols_, nmats_ ) ), offset( nrows_, ncols_, nmats_ ) {}

     inline double& operator()( int i, int j, int k){
         return ( (NumericVector*)(this) )->operator[]( offset( i, j, k) 
) ;
     }

} ;
// [[Rcpp::export]]
Array3 foo(Array3 arr){
     arr(0,0,0) = 1.0 ;
     arr(1,1,1) = 2.0 ;
     return arr ;
}

/*** R
     a <- array( 0, dim = c(4,5,6 ) )
     foo(a)
*/



-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30

R Graph Gallery: http://gallery.r-enthusiasts.com

blog:            http://blog.r-enthusiasts.com
|- http://bit.ly/13SrjxO : highlight 0.4.2
`- http://bit.ly/10X94UM : Mobile version of the graph gallery



More information about the Rcpp-devel mailing list