Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Field of matrices being returned with class matrix instead of list #263

Open
coatless opened this issue Jul 30, 2019 · 3 comments
Open

Field of matrices being returned with class matrix instead of list #263

coatless opened this issue Jul 30, 2019 · 3 comments

Comments

@coatless
Copy link
Contributor

coatless commented Jul 30, 2019

Stumbled across an interesting hiccup in the exporter for arma::field<T> (the generic vector). In particular, the attributes associated with an arma::field<arma::mat> shows as matrix under a class(x) call instead of list. The only way to obtain the list type is to use a typeof() call.

#include<RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
Rcpp::List test_case() {
  
  // Random dimensions
  int N = 5,
      P = 8,
      J = 10,
      K = 3,
      S = 2;

  // Create a 2d matrix
  arma::mat standard_2d_matrix(P, N);

  // Create a 3rd array
  arma::cube standard_3d_array(J, S, N);
  
  // Create a 4D Array
  arma::field<arma::cube> nonstandard_4d_array(N);
  
  // Fill it with cubes
  nonstandard_4d_array.fill(arma::ones<arma::cube>(J, K, S));
  
  return Rcpp::List::create(
    Rcpp::Named("d2", standard_2d_matrix),
    Rcpp::Named("d3", standard_3d_array),
    Rcpp::Named("d4", nonstandard_4d_array)
  );

}

The class issue is shown under d4 being matrix instead of list.

exporter_check = test_case() 

sapply(exporter_check, FUN = class)
#       d2       d3       d4 
# "matrix"  "array" "matrix" 
sapply(exporter_check, FUN = typeof)
#      d2       d3       d4 
# "double" "double"   "list" 

Moreover, the list is registering as a matrix with dim(x) of N x 1 instead of a list without dimensions.

sapply(exporter_check, FUN = dim)
# $d2
# [1] 8 5
# $d3
# [1] 10  2  5
# $d4
# [1] 5 1

And the object structure:

str(exporter_check)
# List of 3
# $ d2: num [1:8, 1:5] 1.49e-154 1.49e-154 2.57e-322 6.95e-310 6.95e-310 ...
# $ d3: num [1:10, 1:2, 1:5] 1.49e-154 1.49e-154 9.96e-320 1.63e-322 1.43e-322 ...
# $ d4:List of 5
#  ..$ : num [1:10, 1:3, 1:2] 1 1 1 1 1 1 1 1 1 1 ...
#  ..$ : num [1:10, 1:3, 1:2] 1 1 1 1 1 1 1 1 1 1 ...
#  ..$ : num [1:10, 1:3, 1:2] 1 1 1 1 1 1 1 1 1 1 ...
#  ..$ : num [1:10, 1:3, 1:2] 1 1 1 1 1 1 1 1 1 1 ...
#  ..$ : num [1:10, 1:3, 1:2] 1 1 1 1 1 1 1 1 1 1 ...
#  ..- attr(*, "dim")= int [1:2] 5 1
@coatless coatless changed the title Field of matrices being returned with class matrix Field of matrices being returned with class matrix instead of list Jul 30, 2019
@coatless
Copy link
Contributor Author

Yeah, so the offending piece of code is setting two dimensions and enforcing a matrix object return instead of a list.

template <typename T>
SEXP wrap( const arma::field<T>& data){
RObject x = wrap( RcppArmadillo::FieldImporter<T>( data ) ) ;
x.attr("dim" ) = Dimension( data.n_rows, data.n_cols ) ;
return x ;
}

@mlampros
Copy link

For anyone else who might stumble upon this issue - as I did - the following worked for me:

// [[Rcpp::export]]
Rcpp::List conv_arma_field_to_rcpp_list(int init_arma_mat = 5,
                                        int dimensions = 6) {

  arma::field<arma::Mat<double> > Field_obj(init_arma_mat);

  for (unsigned int s = 0; s < init_arma_mat; s++) {

    int rows_cols = arma::randi<int>(arma::distr_param(dimensions, dimensions));
    Field_obj(s).zeros(rows_cols, rows_cols);
  }

  Rcpp::List list_obj = Rcpp::wrap( Rcpp::RcppArmadillo::FieldImporter< arma::Mat<double> >( Field_obj ) );
  return list_obj;
}

# res = conv_arma_field_to_rcpp_list()

@eddelbuettel
Copy link
Member

This should now be fixed, albeit behind a #define that has to be turned on. See the new unit tests in tests_fields_new.R and the underlying C++ code (with the #define) in fields_new.cpp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants