From 214a686e28ec9da86f271de5fea65a57e32d9637 Mon Sep 17 00:00:00 2001 From: Ni Date: Wed, 14 Jun 2017 16:20:30 -0500 Subject: [PATCH 1/8] Add support for dtCMatrix&dsCMatrix --- inst/include/RcppArmadilloAs.h | 77 +++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/inst/include/RcppArmadilloAs.h b/inst/include/RcppArmadilloAs.h index efd8db01..b2cd30db 100644 --- a/inst/include/RcppArmadilloAs.h +++ b/inst/include/RcppArmadilloAs.h @@ -77,7 +77,9 @@ namespace traits { private: MATRIX mat ; }; - + + // 14 June 2017 + // Add support for dgCMatrix, dtCMatrix and dsCMatrix template class Exporter< arma::SpMat > { public: @@ -87,23 +89,70 @@ namespace traits { const int RTYPE = Rcpp::traits::r_sexptype_traits::rtype; IntegerVector dims = mat.slot("Dim"); - IntegerVector i = mat.slot("i") ; - IntegerVector p = mat.slot("p") ; - Vector x = mat.slot("x") ; - - // Creating an empty SpMat - arma::SpMat res((unsigned) dims[0], (unsigned) dims[1]); + int nrow = dims[0]; + int ncol = dims[1]; - // Making space for the elements - res.mem_resize((unsigned) x.size()); + // Creating an empty SpMat + arma::SpMat res(static_cast(nrow), static_cast(ncol)); - // Copying elements - std::copy(i.begin(), i.end(), arma::access::rwp(res.row_indices)); - std::copy(p.begin(), p.end(), arma::access::rwp(res.col_ptrs)); - std::copy(x.begin(), x.end(), arma::access::rwp(res.values)); + // Get the type of sparse matrix + std::string type = Rcpp::as(mat.slot("class")); + if (type == "dgCMatrix"){ + IntegerVector i = mat.slot("i"); + IntegerVector p = mat.slot("p"); + Vector x = mat.slot("x"); + + // Making space for the elements + res.mem_resize(static_cast(x.size())); + + // Copying elements + std::copy(i.begin(), i.end(), arma::access::rwp(res.row_indices)); + std::copy(p.begin(), p.end(), arma::access::rwp(res.col_ptrs)); + std::copy(x.begin(), x.end(), arma::access::rwp(res.values)); + } + else if (type == "dtCMatrix"){ + // The following 3 lines might be duplicate, but when the type == dgT or dgR, we have to include the lines inside the conditional statements rather than outside. + IntegerVector i = mat.slot("i"); + IntegerVector p = mat.slot("p"); + Vector x = mat.slot("x"); + std::string diag = Rcpp::as(mat.slot("diag")); + + // Making space for the elements + res.mem_resize(static_cast(x.size())); + + // Copying elements + std::copy(i.begin(), i.end(), arma::access::rwp(res.row_indices)); + std::copy(p.begin(), p.end(), arma::access::rwp(res.col_ptrs)); + std::copy(x.begin(), x.end(), arma::access::rwp(res.values)); + + if (diag == "U"){ + res.diag().ones(); + } + } + else if (type == "dsCMatrix"){ + // The following 3 lines might be duplicate, but when the type == dgT or dgR, we have to include the lines inside the conditional statements rather than outside. + IntegerVector i = mat.slot("i"); + IntegerVector p = mat.slot("p"); + Vector x = mat.slot("x"); + std::string uplo = Rcpp::as(mat.slot("uplo")); + + // Making space for the elements + res.mem_resize(static_cast(x.size())); + + // Copying elements + std::copy(i.begin(), i.end(), arma::access::rwp(res.row_indices)); + std::copy(p.begin(), p.end(), arma::access::rwp(res.col_ptrs)); + std::copy(x.begin(), x.end(), arma::access::rwp(res.values)); + + if(uplo == "U"){ + res = symmatu(res); + }else{ + res = symmatl(res); + } + } // Setting the sentinel - arma::access::rw(res.col_ptrs[(unsigned) dims[1] + 1]) = + arma::access::rw(res.col_ptrs[static_cast(ncol + 1)]) = std::numeric_limits::max(); return res; From 409c2f093000656ade295fdd62203f8dca76ad11 Mon Sep 17 00:00:00 2001 From: Ni Date: Fri, 16 Jun 2017 14:43:49 -0500 Subject: [PATCH 2/8] Indentation --- inst/include/RcppArmadilloAs.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/inst/include/RcppArmadilloAs.h b/inst/include/RcppArmadilloAs.h index b2cd30db..31954255 100644 --- a/inst/include/RcppArmadilloAs.h +++ b/inst/include/RcppArmadilloAs.h @@ -97,7 +97,7 @@ namespace traits { // Get the type of sparse matrix std::string type = Rcpp::as(mat.slot("class")); - if (type == "dgCMatrix"){ + if (type == "dgCMatrix") { IntegerVector i = mat.slot("i"); IntegerVector p = mat.slot("p"); Vector x = mat.slot("x"); @@ -110,7 +110,7 @@ namespace traits { std::copy(p.begin(), p.end(), arma::access::rwp(res.col_ptrs)); std::copy(x.begin(), x.end(), arma::access::rwp(res.values)); } - else if (type == "dtCMatrix"){ + else if (type == "dtCMatrix") { // The following 3 lines might be duplicate, but when the type == dgT or dgR, we have to include the lines inside the conditional statements rather than outside. IntegerVector i = mat.slot("i"); IntegerVector p = mat.slot("p"); @@ -125,11 +125,11 @@ namespace traits { std::copy(p.begin(), p.end(), arma::access::rwp(res.col_ptrs)); std::copy(x.begin(), x.end(), arma::access::rwp(res.values)); - if (diag == "U"){ + if (diag == "U") { res.diag().ones(); } } - else if (type == "dsCMatrix"){ + else if (type == "dsCMatrix") { // The following 3 lines might be duplicate, but when the type == dgT or dgR, we have to include the lines inside the conditional statements rather than outside. IntegerVector i = mat.slot("i"); IntegerVector p = mat.slot("p"); @@ -144,9 +144,9 @@ namespace traits { std::copy(p.begin(), p.end(), arma::access::rwp(res.col_ptrs)); std::copy(x.begin(), x.end(), arma::access::rwp(res.values)); - if(uplo == "U"){ + if (uplo == "U") { res = symmatu(res); - }else{ + } else { res = symmatl(res); } } From c74a0b86dbf73aa7508320b4f01a11771529948b Mon Sep 17 00:00:00 2001 From: Ni Date: Fri, 16 Jun 2017 16:57:04 -0500 Subject: [PATCH 3/8] Add unit test for dtc2dgc --- inst/unitTests/cpp/sparse.cpp | 37 +++++++++++++++++++++++++++++++++++ inst/unitTests/runit.sparse.R | 17 ++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/inst/unitTests/cpp/sparse.cpp b/inst/unitTests/cpp/sparse.cpp index 93e7e590..60609322 100644 --- a/inst/unitTests/cpp/sparse.cpp +++ b/inst/unitTests/cpp/sparse.cpp @@ -77,3 +77,40 @@ Rcpp::List sparseList(Rcpp::List l) { return Rcpp::List::create(mat1, mat2); } + +// [[Rcpp::export]] +arma::sp_mat dtc2dgc(S4 mat){ + IntegerVector dims = mat.slot("Dim"); + int nrow = dims[0]; + int ncol = dims[1]; + + // Creating an empty SpMat + arma::sp_mat res(static_cast(nrow), static_cast(ncol)); + + // Get the type of sparse matrix + std::string type = Rcpp::as(mat.slot("class")); + if (type == "dtCMatrix") { + IntegerVector i = mat.slot("i"); + IntegerVector p = mat.slot("p"); + Vector x = mat.slot("x"); + std::string diag = Rcpp::as(mat.slot("diag")); + + // Making space for the elements + res.mem_resize(static_cast(x.size())); + + // Copying elements + std::copy(i.begin(), i.end(), arma::access::rwp(res.row_indices)); + std::copy(p.begin(), p.end(), arma::access::rwp(res.col_ptrs)); + std::copy(x.begin(), x.end(), arma::access::rwp(res.values)); + + if (diag == "U") { + res.diag().ones(); + } + } + + // Setting the sentinel + arma::access::rw(res.col_ptrs[static_cast(ncol + 1)]) = + std::numeric_limits::max(); + + return res; +} diff --git a/inst/unitTests/runit.sparse.R b/inst/unitTests/runit.sparse.R index 86aec124..7efa2a59 100644 --- a/inst/unitTests/runit.sparse.R +++ b/inst/unitTests/runit.sparse.R @@ -91,5 +91,22 @@ if (.runThisTest) { l <- list(SM, SM) checkEquals(l, sparseList(l), msg="sparseList") } + + test.dtc2dgc <- function() { + mtxt <- c("0 0 0 3", + "0 0 7 0", + "0 0 0 0", + "0 0 0 0") + M <- as.matrix(read.table(textConnection(mtxt))) + dimnames(M) <- NULL + dtc <- Matrix(M, sparse=TRUE) + dgc <- as(dtc, "dgCMatrix") + + checkEquals(dgc, dtc2dgc(dtc), msg="dtc2dgc") + } + + + + } From 04faf5813acb5b31e883de6f6068d33cba7d7ac9 Mon Sep 17 00:00:00 2001 From: binxiangni Date: Fri, 16 Jun 2017 20:06:49 -0500 Subject: [PATCH 4/8] Fix bug --- inst/unitTests/cpp/sparse.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inst/unitTests/cpp/sparse.cpp b/inst/unitTests/cpp/sparse.cpp index 60609322..8877a9be 100644 --- a/inst/unitTests/cpp/sparse.cpp +++ b/inst/unitTests/cpp/sparse.cpp @@ -79,7 +79,8 @@ Rcpp::List sparseList(Rcpp::List l) { } // [[Rcpp::export]] -arma::sp_mat dtc2dgc(S4 mat){ +arma::sp_mat dtc2dgc(SEXP S){ + S4 mat = S; IntegerVector dims = mat.slot("Dim"); int nrow = dims[0]; int ncol = dims[1]; @@ -92,7 +93,7 @@ arma::sp_mat dtc2dgc(S4 mat){ if (type == "dtCMatrix") { IntegerVector i = mat.slot("i"); IntegerVector p = mat.slot("p"); - Vector x = mat.slot("x"); + IntegerVector x = mat.slot("x"); std::string diag = Rcpp::as(mat.slot("diag")); // Making space for the elements From ba58bd2fbadf7cb2c0577f2ad3142dc5ff0ea8f6 Mon Sep 17 00:00:00 2001 From: binxiangni Date: Sat, 17 Jun 2017 09:41:36 -0500 Subject: [PATCH 5/8] Add unit tests for dtCMatrix & dsCMatrix --- inst/unitTests/cpp/sparse.cpp | 38 ----------------------------------- inst/unitTests/runit.sparse.R | 23 ++++++++++++++++----- 2 files changed, 18 insertions(+), 43 deletions(-) diff --git a/inst/unitTests/cpp/sparse.cpp b/inst/unitTests/cpp/sparse.cpp index 8877a9be..93e7e590 100644 --- a/inst/unitTests/cpp/sparse.cpp +++ b/inst/unitTests/cpp/sparse.cpp @@ -77,41 +77,3 @@ Rcpp::List sparseList(Rcpp::List l) { return Rcpp::List::create(mat1, mat2); } - -// [[Rcpp::export]] -arma::sp_mat dtc2dgc(SEXP S){ - S4 mat = S; - IntegerVector dims = mat.slot("Dim"); - int nrow = dims[0]; - int ncol = dims[1]; - - // Creating an empty SpMat - arma::sp_mat res(static_cast(nrow), static_cast(ncol)); - - // Get the type of sparse matrix - std::string type = Rcpp::as(mat.slot("class")); - if (type == "dtCMatrix") { - IntegerVector i = mat.slot("i"); - IntegerVector p = mat.slot("p"); - IntegerVector x = mat.slot("x"); - std::string diag = Rcpp::as(mat.slot("diag")); - - // Making space for the elements - res.mem_resize(static_cast(x.size())); - - // Copying elements - std::copy(i.begin(), i.end(), arma::access::rwp(res.row_indices)); - std::copy(p.begin(), p.end(), arma::access::rwp(res.col_ptrs)); - std::copy(x.begin(), x.end(), arma::access::rwp(res.values)); - - if (diag == "U") { - res.diag().ones(); - } - } - - // Setting the sentinel - arma::access::rw(res.col_ptrs[static_cast(ncol + 1)]) = - std::numeric_limits::max(); - - return res; -} diff --git a/inst/unitTests/runit.sparse.R b/inst/unitTests/runit.sparse.R index 7efa2a59..de172beb 100644 --- a/inst/unitTests/runit.sparse.R +++ b/inst/unitTests/runit.sparse.R @@ -102,11 +102,24 @@ if (.runThisTest) { dtc <- Matrix(M, sparse=TRUE) dgc <- as(dtc, "dgCMatrix") - checkEquals(dgc, dtc2dgc(dtc), msg="dtc2dgc") + checkEquals(dgc, asSpMat(dtc), msg="asSpMat") + + dtc@diag <- "U" + dgc <- as(dtc, "dgCMatrix") + checkEquals(dgc, asSpMat(dtc), msg="asSpMat") } - - - - + test.dsc2dgc <- function() { + mtxt <- c("10 0 1 0 3", + "0 10 0 1 0", + "1 0 10 0 1", + "0 1 0 10 0", + "3 0 1 0 10") + M <- as.matrix(read.table(textConnection(mtxt))) + dimnames(M) <- NULL + dsc <- Matrix(M, sparse=TRUE) + dgc <- as(dsc, "dgCMatrix") + + checkEquals(dgc, asSpMat(dsc), msg="asSpMat") + } } From ecbb0d01c3c5d2967856385541454780490bb4e7 Mon Sep 17 00:00:00 2001 From: binxiangni Date: Sat, 17 Jun 2017 11:19:09 -0500 Subject: [PATCH 6/8] Add conversion and unit tests for dtCMatrix & dsCMatrix --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6526419f..7fac8f4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-06-17 Binxiang Ni + + * inst/include/RcppArmadilloAs.h: Add conversion for dtCMatrix & dsCMatrix + * inst/unitTests/runit.sparse.R: Add unit tests for the conversion for dtCMatrix & dsCMatrix + 2017-06-04 Dirk Eddelbuettel * configure.ac: Whitespace changes From f5d2f7487395405cbe84b3ad78a2641695c3b408 Mon Sep 17 00:00:00 2001 From: Binxiang Ni Date: Sat, 17 Jun 2017 11:21:14 -0500 Subject: [PATCH 7/8] Update ChangeLog --- ChangeLog | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7fac8f4d..e8955809 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ 2017-06-17 Binxiang Ni - * inst/include/RcppArmadilloAs.h: Add conversion for dtCMatrix & dsCMatrix - * inst/unitTests/runit.sparse.R: Add unit tests for the conversion for dtCMatrix & dsCMatrix + * inst/include/RcppArmadilloAs.h: Add conversion for dtCMatrix & dsCMatrix + * inst/unitTests/runit.sparse.R: Add unit tests for the conversion for + dtCMatrix & dsCMatrix 2017-06-04 Dirk Eddelbuettel From 457c6c22a957a395c37c99e9459b0d3e72e7ee77 Mon Sep 17 00:00:00 2001 From: binxiangni Date: Sat, 17 Jun 2017 12:01:53 -0500 Subject: [PATCH 8/8] Add unit test for low triangle dsCMatrix --- inst/unitTests/runit.sparse.R | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/inst/unitTests/runit.sparse.R b/inst/unitTests/runit.sparse.R index de172beb..30b68d18 100644 --- a/inst/unitTests/runit.sparse.R +++ b/inst/unitTests/runit.sparse.R @@ -121,5 +121,10 @@ if (.runThisTest) { dgc <- as(dsc, "dgCMatrix") checkEquals(dgc, asSpMat(dsc), msg="asSpMat") + + dsc <- t(dsc) + dgc <- as(dsc, "dgCMatrix") + + checkEquals(dgc, asSpMat(dsc), msg="asSpMat") } }