diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index cea7ca2..cb17061 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -61,7 +61,7 @@ jobs: while read -r cmd do eval sudo $cmd - done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))') + done < <(Rscript -e 'writeLines(c(remotes::system_requirements("ubuntu", "20.04"), remotes::system_requirements("ubuntu", "20.04", package="curl")))') - name: Install dependencies run: | diff --git a/DESCRIPTION b/DESCRIPTION index 581b7a3..76a598c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: natcpp Title: Fast C++ Primitives for the 'NeuroAnatomy Toolbox' -Version: 0.1.0.9000 +Version: 0.1.1 Authors@R: person(given = "Gregory", family = "Jefferis", diff --git a/NAMESPACE b/NAMESPACE index dc7c100..d8be76d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,7 @@ # Generated by roxygen2: do not edit by hand export(c_EdgeListFromSegList) +export(c_ListofMatrixRows) export(c_listlengths) export(c_seglengths) export(c_topntail) diff --git a/NEWS.md b/NEWS.md index 9b956ea..97303df 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,9 @@ # natcpp (development version) +# natcpp 0.1.1 + +* adds `c_ListofMatrixRows()` + # natcpp 0.1.0 * First version of the package with basic functions for manipulating segment diff --git a/R/RcppExports.R b/R/RcppExports.R index 6620c46..d29e627 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -20,6 +20,30 @@ c_total_cable <- function(sl, x, y, z) { .Call(`_natcpp_c_total_cable`, sl, x, y, z) } +#' Convert a matrix into list of row vectors +#' +#' @details Typically this will be for 3D coordinates but there are no limits +#' on row length. +#' @param object An integer, numeric, character or logical matrix of N rows and +#' M columns +#' @return a list containing N vectors of length M corresponding to the rows of +#' \code{object}. +#' @export +#' @examples +#' \dontrun{ +#' library(nat) +#' xyz=xyzmatrix(Cell07PNs) +#' mat2list = function(m) { +#' um=unname(m) +#' lapply(1:nrow(um), function(i) um[i,]) +#' } +#' bench::mark(rcpp=c_ListofMatrixRows(xyz), r=mat2list(xyz)) +#' } +#' @export +c_ListofMatrixRows <- function(object) { + .Call(`_natcpp_c_ListofMatrixRows`, object) +} + #' A simple function to compute the lengths of the elements of an R list #' #' @details This is equivalent to the \code{base::lengths} however it it much diff --git a/man/c_ListofMatrixRows.Rd b/man/c_ListofMatrixRows.Rd new file mode 100644 index 0000000..02a4f44 --- /dev/null +++ b/man/c_ListofMatrixRows.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/RcppExports.R +\name{c_ListofMatrixRows} +\alias{c_ListofMatrixRows} +\title{Convert a matrix into list of row vectors} +\usage{ +c_ListofMatrixRows(object) +} +\arguments{ +\item{object}{An integer, numeric, character or logical matrix of N rows and +M columns} +} +\value{ +a list containing N vectors of length M corresponding to the rows of + \code{object}. +} +\description{ +Convert a matrix into list of row vectors +} +\details{ +Typically this will be for 3D coordinates but there are no limits + on row length. +} +\examples{ +\dontrun{ +library(nat) +xyz=xyzmatrix(Cell07PNs) +mat2list = function(m) { +um=unname(m) +lapply(1:nrow(um), function(i) um[i,]) +} +bench::mark(rcpp=c_ListofMatrixRows(xyz), r=mat2list(xyz)) +} +} diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 666003e..aed385b 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -38,6 +38,17 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// c_ListofMatrixRows +List c_ListofMatrixRows(const SEXP& object); +RcppExport SEXP _natcpp_c_ListofMatrixRows(SEXP objectSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const SEXP& >::type object(objectSEXP); + rcpp_result_gen = Rcpp::wrap(c_ListofMatrixRows(object)); + return rcpp_result_gen; +END_RCPP +} // c_listlengths IntegerVector c_listlengths(const List& L); RcppExport SEXP _natcpp_c_listlengths(SEXP LSEXP) { @@ -86,6 +97,7 @@ END_RCPP static const R_CallMethodDef CallEntries[] = { {"_natcpp_c_seglengths", (DL_FUNC) &_natcpp_c_seglengths, 4}, {"_natcpp_c_total_cable", (DL_FUNC) &_natcpp_c_total_cable, 4}, + {"_natcpp_c_ListofMatrixRows", (DL_FUNC) &_natcpp_c_ListofMatrixRows, 1}, {"_natcpp_c_listlengths", (DL_FUNC) &_natcpp_c_listlengths, 1}, {"_natcpp_c_topntail", (DL_FUNC) &_natcpp_c_topntail, 1}, {"_natcpp_c_topntail_list", (DL_FUNC) &_natcpp_c_topntail_list, 1}, diff --git a/src/matrix.cpp b/src/matrix.cpp new file mode 100644 index 0000000..e6cac70 --- /dev/null +++ b/src/matrix.cpp @@ -0,0 +1,48 @@ +#include "natcpp.h" + +template +List c_ListofMatrixRowsT(const T &m) { + List L(m.nrow()); + + for(int i=0; i<(m.nrow()); i++) { + // NumericVector v = m( 0 , _ ); + L[i]=m.row(i); + } + return L; +} + + +//' Convert a matrix into list of row vectors +//' +//' @details Typically this will be for 3D coordinates but there are no limits +//' on row length. +//' @param object An integer, numeric, character or logical matrix of N rows and +//' M columns +//' @return a list containing N vectors of length M corresponding to the rows of +//' \code{object}. +//' @export +//' @examples +//' \dontrun{ +//' library(nat) +//' xyz=xyzmatrix(Cell07PNs) +//' mat2list = function(m) { +//' um=unname(m) +//' lapply(1:nrow(um), function(i) um[i,]) +//' } +//' bench::mark(rcpp=c_ListofMatrixRows(xyz), r=mat2list(xyz)) +//' } +//' @export +// [[Rcpp::export]] +List c_ListofMatrixRows(const SEXP &object) { + if (!Rf_isMatrix(object)) + stop("Please provide a matrix!"); + + switch (TYPEOF(object)) + { + case INTSXP: return c_ListofMatrixRowsT(object); + case REALSXP: return c_ListofMatrixRowsT(object); + case CHARSXP: return c_ListofMatrixRowsT(object); + case LGLSXP: return c_ListofMatrixRowsT(object); + } + stop("Unimplemented matrix type!"); +} diff --git a/tests/testthat/test-matrix.R b/tests/testthat/test-matrix.R new file mode 100644 index 0000000..88b6e3f --- /dev/null +++ b/tests/testthat/test-matrix.R @@ -0,0 +1,20 @@ +test_that("multiplication works", { + m=matrix(1:6, ncol=3, byrow = T) + l=list(1:3, 4:6) + colnames(m)=c("X","Y","Z") + expect_equal(c_ListofMatrixRows(m), l) + + nm=matrix(rnorm(n = 300), ncol=3) + + expect_equal(c_ListofMatrixRows(nm), + lapply(seq_len(nrow(nm)), function(i) nm[i,])) + + expect_equal(c_ListofMatrixRows(matrix(1L, nrow=2, ncol=0)), + list(integer(), integer())) + expect_equal(c_ListofMatrixRows(matrix(1L, nrow=0, ncol=2)), + list()) + expect_error(c_ListofMatrixRows(l)) + # matrix of lists + ml=matrix(rep(list(1), 4), ncol = 2) + expect_error(c_ListofMatrixRows(ml)) +})