[Rcpp-devel] Three-dimensional vectors example

Christian Gunning xian at unm.edu
Wed Sep 26 08:45:01 CEST 2012


On Tue, Sep 25, 2012 at 3:00 AM,
<rcpp-devel-request at lists.r-forge.r-project.org> wrote:
>
> Someone just asked on StackOverflow about creating 3d arrays:
> http://stackoverflow.com/questions/12569992/constructing-3d-array-in-rcpp
>
> The best I could come up with is below. Did I miss something better?
>
> Full disclosure: The last I needed this, I also needed ops on it, and used
> the arma::cube class from (Rcpp)Armadillo instead.
+    Rcpp::NumericVector v(vs);            // get the data
+    Rcpp::Dimension d(ds);                // get the dimension object
+    Rcpp::NumericVector r(d);             // create (empty) vector
with correct dims

That's a cool example.  I didn't realize there was such a
NumericVector constructor.
For reference, the arma example using the advanced cube constructor is
below (first example).

It looks like the NumericVector(Dimension) constructor only works for
D<=3 (for D=4, I just get a vector back). I realized recently that
arma::field provides a decent way to get arrays with D>3, though
copying in/out is a pain and wrap() returns a matrix of lists (with
each cell containing a matrix).  I'm impressed that wrap() can figure
this out at all!

library(inline)
## 3D, arma
##
fx <- cxxfunction(signature(dat_="numeric", nr="integer",
nc="integer", ns="integer"),
                    plugin="RcppArmadillo", body='
        NumericVector dat(dat_);
        arma::cube mycube(dat.begin(), as<int>(nr), as<int>(nc), as<int>(ns));
        return wrap(mycube);
')
result <- fx( 1:24, 4, 3, 2)


## 4D array.  easily generalizes to field<cube> = 5D
##
fx1 <- cxxfunction(signature(dat_="numeric", dim_="integer"),
                    plugin="RcppArmadillo", body='
        NumericVector dat(dat_);
        IntegerVector dim(dim_);
        NumericVector::iterator it = dat.begin();

        arma::field<arma::mat> myarray(dim[2], dim[3]);

        for (int ii=0; ii<dim[2]; ii++) {
            for (int jj=0; jj<dim[3]; jj++) {
                myarray(ii, jj) = arma::mat( it, dim[0], dim[1]);
                Rf_PrintValue(wrap(myarray(ii, jj)));
                it += ( dim[0] * dim[1]);
            }
        }
        return wrap(myarray);
')
result1 <- fx1( 1:120, c(5, 4, 3, 2))


-Christian
-- 
A man, a plan, a cat, a ham, a yak, a yam, a hat, a canal – Panama!


More information about the Rcpp-devel mailing list