From 4c6addd4292ac05b3122e3dd61b16c0416b8306a Mon Sep 17 00:00:00 2001 From: Jonathan Berrisch Date: Tue, 9 Nov 2021 18:06:46 +0100 Subject: [PATCH 1/4] Fix dim problem with arma::field input and output This the dims of arma::field when specified as input or output. This implementation works with 1d, 2d and 3d fields. --- inst/include/RcppArmadilloAs.h | 24 ++++++++++++++++++++---- inst/include/RcppArmadilloWrap.h | 2 +- inst/tinytest/test_rcpparmadillo.R | 5 +++-- src/RcppExports.cpp | 5 +++++ 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/inst/include/RcppArmadilloAs.h b/inst/include/RcppArmadilloAs.h index 37cc8e0e..52766497 100644 --- a/inst/include/RcppArmadilloAs.h +++ b/inst/include/RcppArmadilloAs.h @@ -32,10 +32,26 @@ namespace traits { Exporter(SEXP x) : data(x){} inline arma::field get() { - size_t n = data.size() ; - arma::field out( n ) ; - for(size_t i=0; i(data[i]) ; + size_t n = data.size(); + arma::ivec dims = data.attr("dim"); + arma::field out; + + if (dims.n_elem == 1) + { + out.set_size(n); + } + else if (dims.n_elem == 2) + { + out.set_size(dims(0), dims(1)); + } + else if (dims.n_elem == 3) + { + out.set_size(dims(0), dims(1), dims(2)); + } + + for (size_t i = 0; i < n; i++) + { + out(i) = as(data[i]); } return out ; } diff --git a/inst/include/RcppArmadilloWrap.h b/inst/include/RcppArmadilloWrap.h index 42ec8932..ba5126d7 100644 --- a/inst/include/RcppArmadilloWrap.h +++ b/inst/include/RcppArmadilloWrap.h @@ -149,7 +149,7 @@ namespace Rcpp{ template SEXP wrap( const arma::field& data){ RObject x = wrap( RcppArmadillo::FieldImporter( data ) ) ; - x.attr("dim" ) = Dimension( data.n_rows, data.n_cols ) ; + x.attr("dim" ) = Dimension( data.n_rows, data.n_cols, data.n_slices ) ; return x ; } diff --git a/inst/tinytest/test_rcpparmadillo.R b/inst/tinytest/test_rcpparmadillo.R index 59cd1b1b..b20134ec 100644 --- a/inst/tinytest/test_rcpparmadillo.R +++ b/inst/tinytest/test_rcpparmadillo.R @@ -37,8 +37,9 @@ expect_equal( res[[2]][[2]], matrix(0, ncol = 5, nrow=1))#, msg = "zeros(5 expect_equal( res[[3]][[1]], matrix(0, ncol = 1, nrow=5))#, msg = "zeros(1,5)" ) expect_equal( res[[3]][[2]], matrix(0, ncol = 1, nrow=5))#, msg = "zeros(1,5)" ) -expect_equal( res[[4]][[1]], matrix(0:3, ncol = 2, nrow=2))#, msg = "field" ) -expect_equal( res[[4]][[2]], matrix(letters[1:4], ncol = 2, nrow=2))#, msg = "field" ) +# TODO: Revisit field tests later and fix see https://github.com/RcppCore/RcppArmadillo/pull/352 +# expect_equal( res[[4]][[1]], matrix(0:3, ncol = 2, nrow=2))#, msg = "field" ) +# expect_equal( res[[4]][[2]], matrix(letters[1:4], ncol = 2, nrow=2))#, msg = "field" ) # test.wrap.Glue <- function(){ diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 35eaa69b..024c6bb7 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -6,6 +6,11 @@ using namespace Rcpp; +#ifdef RCPP_USE_GLOBAL_ROSTREAM +Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); +Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); +#endif + // armadillo_version Rcpp::IntegerVector armadillo_version(bool single); RcppExport SEXP _RcppArmadillo_armadillo_version(SEXP singleSEXP) { From 1cc59d17cc0b761c1a807e1eb260825a45d04f2e Mon Sep 17 00:00:00 2001 From: Jonathan Berrisch Date: Tue, 9 Nov 2021 18:06:47 +0100 Subject: [PATCH 2/4] Introduce 2 macros: opt into fixed field behavior --- inst/include/RcppArmadilloAs.h | 32 +++++++++++++++--------------- inst/include/RcppArmadilloConfig.h | 9 +++++++++ inst/include/RcppArmadilloWrap.h | 6 +++++- inst/tinytest/test_rcpparmadillo.R | 4 ++-- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/inst/include/RcppArmadilloAs.h b/inst/include/RcppArmadilloAs.h index 52766497..9ed0f754 100644 --- a/inst/include/RcppArmadilloAs.h +++ b/inst/include/RcppArmadilloAs.h @@ -33,22 +33,22 @@ namespace traits { inline arma::field get() { size_t n = data.size(); - arma::ivec dims = data.attr("dim"); - arma::field out; - - if (dims.n_elem == 1) - { - out.set_size(n); - } - else if (dims.n_elem == 2) - { - out.set_size(dims(0), dims(1)); - } - else if (dims.n_elem == 3) - { - out.set_size(dims(0), dims(1), dims(2)); - } - + arma::field out(n); + # if defined(RCPP_ARMADILLO_FIX_FieldExporter) + arma::ivec dims = data.attr("dim"); + if (dims.n_elem == 1) + { + out.set_size(n); + } + else if (dims.n_elem == 2) + { + out.set_size(dims(0), dims(1)); + } + else if (dims.n_elem == 3) + { + out.set_size(dims(0), dims(1), dims(2)); + } + # endif for (size_t i = 0; i < n; i++) { out(i) = as(data[i]); diff --git a/inst/include/RcppArmadilloConfig.h b/inst/include/RcppArmadilloConfig.h index 49090950..fe4e2341 100644 --- a/inst/include/RcppArmadilloConfig.h +++ b/inst/include/RcppArmadilloConfig.h @@ -135,5 +135,14 @@ //#define RCPP_ARMADILLO_RETURN_ROWVEC_AS_VECTOR //#define RCPP_ARMADILLO_RETURN_ANYVEC_AS_VECTOR +// To preserve all dims of arma::field when passing to R the following macro +// can be defined before including RcppArmadillo.h. +// see https://github.com/RcppCore/RcppArmadillo/pull/352 +// #define RCPP_ARMADILLO_FIX_FieldImporter + +// To preserve all dims of and arma::field input argument when passing to C++ +// the following macro can be defined before including RcppArmadillo.h. +// see https://github.com/RcppCore/RcppArmadillo/pull/352 +// #define RCPP_ARMADILLO_FIX_FieldExporter #endif diff --git a/inst/include/RcppArmadilloWrap.h b/inst/include/RcppArmadilloWrap.h index ba5126d7..b290da67 100644 --- a/inst/include/RcppArmadilloWrap.h +++ b/inst/include/RcppArmadilloWrap.h @@ -149,7 +149,11 @@ namespace Rcpp{ template SEXP wrap( const arma::field& data){ RObject x = wrap( RcppArmadillo::FieldImporter( data ) ) ; - x.attr("dim" ) = Dimension( data.n_rows, data.n_cols, data.n_slices ) ; + # if defined(RCPP_ARMADILLO_FIX_FieldImporter) + x.attr("dim" ) = Dimension( data.n_rows, data.n_cols, data.n_slices ) ; + #else + x.attr("dim" ) = Dimension( data.n_rows, data.n_cols ) ; + #endif return x ; } diff --git a/inst/tinytest/test_rcpparmadillo.R b/inst/tinytest/test_rcpparmadillo.R index b20134ec..e286ee3e 100644 --- a/inst/tinytest/test_rcpparmadillo.R +++ b/inst/tinytest/test_rcpparmadillo.R @@ -38,8 +38,8 @@ expect_equal( res[[3]][[1]], matrix(0, ncol = 1, nrow=5))#, msg = "zeros(1, expect_equal( res[[3]][[2]], matrix(0, ncol = 1, nrow=5))#, msg = "zeros(1,5)" ) # TODO: Revisit field tests later and fix see https://github.com/RcppCore/RcppArmadillo/pull/352 -# expect_equal( res[[4]][[1]], matrix(0:3, ncol = 2, nrow=2))#, msg = "field" ) -# expect_equal( res[[4]][[2]], matrix(letters[1:4], ncol = 2, nrow=2))#, msg = "field" ) +expect_equal( res[[4]][[1]], matrix(0:3, ncol = 2, nrow=2))#, msg = "field" ) +expect_equal( res[[4]][[2]], matrix(letters[1:4], ncol = 2, nrow=2))#, msg = "field" ) # test.wrap.Glue <- function(){ From a0c4e10a0892e48ac66ff76a0d813a643533b42a Mon Sep 17 00:00:00 2001 From: Jonathan Berrisch Date: Tue, 9 Nov 2021 18:06:47 +0100 Subject: [PATCH 3/4] Handle dimensionless lists as field input This also fixes a problem occuring with cIRT::direct_sum() --- inst/include/RcppArmadilloAs.h | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/inst/include/RcppArmadilloAs.h b/inst/include/RcppArmadilloAs.h index 9ed0f754..dc96ad1d 100644 --- a/inst/include/RcppArmadilloAs.h +++ b/inst/include/RcppArmadilloAs.h @@ -22,6 +22,8 @@ #ifndef RcppArmadillo__RcppArmadilloAs__h #define RcppArmadillo__RcppArmadilloAs__h +#define RCPP_ARMADILLO_FIX_FieldExporter + namespace Rcpp{ namespace traits { @@ -30,23 +32,24 @@ namespace traits { class Exporter< arma::field > { public: Exporter(SEXP x) : data(x){} - inline arma::field get() { size_t n = data.size(); arma::field out(n); # if defined(RCPP_ARMADILLO_FIX_FieldExporter) - arma::ivec dims = data.attr("dim"); - if (dims.n_elem == 1) - { - out.set_size(n); - } - else if (dims.n_elem == 2) - { - out.set_size(dims(0), dims(1)); - } - else if (dims.n_elem == 3) - { - out.set_size(dims(0), dims(1), dims(2)); + if(!Rf_isNull(data.attr("dim"))){ + arma::ivec dims = data.attr("dim"); + if (dims.n_elem == 1) + { + out.set_size(n); + } + else if (dims.n_elem == 2) + { + out.set_size(dims(0), dims(1)); + } + else if (dims.n_elem == 3) + { + out.set_size(dims(0), dims(1), dims(2)); + } } # endif for (size_t i = 0; i < n; i++) From ec2e7ecd911cf6bdabc8417fd1a805737c14f5db Mon Sep 17 00:00:00 2001 From: Jonathan Berrisch Date: Tue, 9 Nov 2021 18:06:47 +0100 Subject: [PATCH 4/4] Remove #define statement that was added by mistake --- inst/include/RcppArmadilloAs.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/inst/include/RcppArmadilloAs.h b/inst/include/RcppArmadilloAs.h index dc96ad1d..7ae27111 100644 --- a/inst/include/RcppArmadilloAs.h +++ b/inst/include/RcppArmadilloAs.h @@ -22,8 +22,6 @@ #ifndef RcppArmadillo__RcppArmadilloAs__h #define RcppArmadillo__RcppArmadilloAs__h -#define RCPP_ARMADILLO_FIX_FieldExporter - namespace Rcpp{ namespace traits {