[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