12

I am trying to map a 1D array onto 3D array using provided list of dimensions.

Here are my components:

SEXP data; // my 1D array
// I can initialise new 3D vector in the following way:
NumericVector vector(Dimension(2, 2, 2);
// or the following:
NumericVector vector(data.begin(), data.end());

What I didn't figure out is how can I create a NumericVector that would have both my data and the desired dimensions.

Datageek
  • 25,977
  • 6
  • 66
  • 70

2 Answers2

22

There is a shorter solution. You can reshape your data using .attr. The data can be created or given as an input - it does not matter. See below:

library("Rcpp")

cppFunction(code='
NumericVector arrayC(NumericVector input, IntegerVector dim) { 
  input.attr("dim") = dim;
  return input;
}
')
x = 1:8
arrayC(x, c(2,2,2))
## , , 1
## 
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## 
## , , 2
## 
##      [,1] [,2]
## [1,]    5    7
## [2,]    6    8
Vyga
  • 894
  • 8
  • 8
6

It is doable, but a little painful. I guess a decent (and tested) contribution for new constructor or helper function would be appreciated.

In the meantime, you can do what the example below does. But be careful about row-major and col-major etc. Another option is RcppArmadillo which has a proper 'Cube' type generalizing matrices to 3-d.

R> library(inline)
R> fx <- cxxfunction(signature(vs="numeric", ds="integer"), plugin="Rcpp", body='
+    Rcpp::NumericVector v(vs);            // get the data
+    Rcpp::Dimension d(ds);                // get the dim object
+    Rcpp::NumericVector r(d);             // create vec. with correct dims
+    std::copy(v.begin(), v.end(), r.begin());  // and copy
+    return Rcpp::List::create(v, d, r);
+ ')
R> fx(1:8, c(2,2,2))
[[1]]
[1] 1 2 3 4 5 6 7 8

[[2]]
[1] 2 2 2

[[3]]
, , 1

     [,1] [,2]
[1,]    1    3
[2,]    2    4

, , 2

     [,1] [,2]
[1,]    5    7
[2,]    6    8


R>
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Agree with the new constructor, would be very useful. I may look into it when I will understand how things work in Rcpp. – Datageek Sep 25 '12 at 11:08
  • 2
    FWIW, adding yet another constructor to the already bloated `Vector` template seems like a bad idea. You can achieve the same with a free function, or a dedicated Array class, like the one in Rcpp11. – Romain Francois Apr 30 '14 at 08:36
  • 4
    Thanks for updating a two-year old answer. FWIW I have been using RcppArmadillo on several occassions as Armadillo has `Cube` as a first class object. Works for me. – Dirk Eddelbuettel Apr 30 '14 at 11:09