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
_______________________________________________
Rcpp-devel mailing list
[email protected]
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel