diff --git a/.travis.yml b/.travis.yml index 85bc18c..e76f10c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,9 @@ os: - linux - osx +r_build_args: --no-build-vignettes --no-manual --no-resave-data +r_check_args: --no-build-vignettes --no-manual + r_binary_packages: - Rcpp - bigmemory.sri diff --git a/NAMESPACE b/NAMESPACE index d62737c..5d479af 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -17,7 +17,9 @@ export(is.separated) export(is.shared) export(is.sub.big.matrix) export(morder) +export(morderCols) export(mpermute) +export(mpermuteCols) export(mwhich) export(read.big.matrix) export(shared.name) diff --git a/R/RcppExports.R b/R/RcppExports.R index 549a9de..8b6d610 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -13,6 +13,18 @@ ReorderBigMatrix <- function(address, orderVec) { invisible(.Call('bigmemory_ReorderBigMatrix', PACKAGE = 'bigmemory', address, orderVec)) } +ReorderRIntMatrixCols <- function(matrixVector, nrow, ncol, orderVec) { + invisible(.Call('bigmemory_ReorderRIntMatrixCols', PACKAGE = 'bigmemory', matrixVector, nrow, ncol, orderVec)) +} + +ReorderRNumericMatrixCols <- function(matrixVector, nrow, ncol, orderVec) { + invisible(.Call('bigmemory_ReorderRNumericMatrixCols', PACKAGE = 'bigmemory', matrixVector, nrow, ncol, orderVec)) +} + +ReorderBigMatrixCols <- function(address, orderVec) { + invisible(.Call('bigmemory_ReorderBigMatrixCols', PACKAGE = 'bigmemory', address, orderVec)) +} + OrderRIntMatrix <- function(matrixVector, nrow, columns, naLast, decreasing) { .Call('bigmemory_OrderRIntMatrix', PACKAGE = 'bigmemory', matrixVector, nrow, columns, naLast, decreasing) } @@ -25,6 +37,18 @@ OrderBigMatrix <- function(address, columns, naLast, decreasing) { .Call('bigmemory_OrderBigMatrix', PACKAGE = 'bigmemory', address, columns, naLast, decreasing) } +OrderRIntMatrixCols <- function(matrixVector, nrow, ncol, rows, naLast, decreasing) { + .Call('bigmemory_OrderRIntMatrixCols', PACKAGE = 'bigmemory', matrixVector, nrow, ncol, rows, naLast, decreasing) +} + +OrderRNumericMatrixCols <- function(matrixVector, nrow, ncol, rows, naLast, decreasing) { + .Call('bigmemory_OrderRNumericMatrixCols', PACKAGE = 'bigmemory', matrixVector, nrow, ncol, rows, naLast, decreasing) +} + +OrderBigMatrixCols <- function(address, rows, naLast, decreasing) { + .Call('bigmemory_OrderBigMatrixCols', PACKAGE = 'bigmemory', address, rows, naLast, decreasing) +} + CCleanIndices <- function(indices, rc) { .Call('bigmemory_CCleanIndices', PACKAGE = 'bigmemory', indices, rc) } diff --git a/R/bigmemory.R b/R/bigmemory.R index de20f06..2caba66 100644 --- a/R/bigmemory.R +++ b/R/bigmemory.R @@ -1796,29 +1796,41 @@ morder <- function(x, cols, na.last=TRUE, decreasing = FALSE) { stop("Bad column indices.") } + + switch(class(x), + "big.matrix" = OrderBigMatrix(x@address, as.double(cols), + as.integer(na.last), as.logical(decreasing) ), + "matrix" = switch(typeof(x), + 'integer' = OrderRIntMatrix(x, nrow(x), as.double(cols), + as.integer(na.last), as.logical(decreasing) ), + 'double' = OrderRNumericMatrix(x, nrow(x), as.double(cols), + as.integer(na.last), as.logical(decreasing) ), + stop("Unsupported matrix value type.")), + stop("unsupported matrix type") + ) +} - if (class(x) == 'big.matrix') - { - return(OrderBigMatrix(x@address, as.double(cols), - as.integer(na.last), as.logical(decreasing) )) - } - else if (class(x) == 'matrix') +#' @rdname morder +#' @export +morderCols <- function(x, rows, na.last=TRUE, decreasing = FALSE) +{ + if (is.character(rows)) rows <- mmap( rows, rownames(x) ) + if (sum(rows > nrow(x)) > 0 | sum(rows < 1) > 0 | sum(is.na(rows) > 0)) { - if (typeof(x) == 'integer') - { - return(OrderRIntMatrix(x, nrow(x), as.double(cols), - as.integer(na.last), as.logical(decreasing) )) - } - else if (typeof(x) == 'double') - { - return(OrderRNumericMatrix(x, nrow(x), as.double(cols), - as.integer(na.last), as.logical(decreasing) )) - } - else - stop("Unsupported matrix value type.") + stop("Bad row indices.") } - else - stop("Unsupported matrix type.") + + switch(class(x), + "big.matrix" = OrderBigMatrixCols(x@address, as.double(rows), + as.integer(na.last), as.logical(decreasing) ), + "matrix" = switch(typeof(x), + 'integer' = OrderRIntMatrixCols(x, nrow(x), ncol(x), as.double(rows), + as.integer(na.last), as.logical(decreasing) ), + 'double' = OrderRNumericMatrixCols(x, nrow(x), ncol(x), as.double(rows), + as.integer(na.last), as.logical(decreasing) ), + stop("Unsupported matrix value type.")), + stop("unsupported matrix type") + ) } #' @rdname morder @@ -1848,28 +1860,59 @@ mpermute <- function(x, order=NULL, cols=NULL, allow.duplicates=FALSE, ...) else order = morder(x, cols, ...) - if (class(x) == 'big.matrix') - { - ReorderBigMatrix(x@address, order) - } - else if (class(x) == 'matrix') + switch(class(x), + "big.matrix" = ReorderBigMatrix(x@address, order), + "matrix" = switch(typeof(x), + 'integer' = ReorderRIntMatrix(x, nrow(x), ncol(x), order), + 'double' = ReorderRNumericMatrix(x, nrow(x), ncol(x), order), + stop("Unsupported matrix value type.")), + stop("invalid class") + ) + + return(invisible(TRUE)) + +} + +#' @rdname morder +#' @export +mpermuteCols <- function(x, order=NULL, rows=NULL, allow.duplicates=FALSE, ...) +{ + if (is.null(order) && is.null(rows)) + stop("You must specify either order or cols.") + + if (!is.null(order) && !is.null(rows)) + stop("You must specify either order or cols.") + + if (!is.null(order)) { - if (typeof(x) == 'integer') - { - OrderRIntMatrix(x, nrow(x), ncol(x), order) - } - else if (typeof(x) == 'double') - { - ReorderRNumericMatrix(x, nrow(x), ncol(x), order) - } - else - stop("Unsupported matrix value type.") + if (length(order) != ncol(x)) + stop("order parameter must have the same length as ncol(x)") + + if (!allow.duplicates && sum(duplicated(order)) > 0) + stop("order parameter contains duplicated entries.") + + r = range(order) + if (is.na(r[1])) + stop("order parameter contains NAs") + if (r[1] < 1 || r[2] > nrow(x)) + stop("order parameter contains values that are out-of-range.") } + else + order = morderCols(x, rows, ...) + + switch(class(x), + "big.matrix" = ReorderBigMatrixCols(x@address, order), + "matrix" = switch(typeof(x), + 'integer' = ReorderRIntMatrixCols(x, nrow(x), ncol(x), order), + 'double' = ReorderRNumericMatrixCols(x, nrow(x), ncol(x), order), + stop("Unsupported matrix value type.")), + stop("unimplemented class") + ) + return(invisible(TRUE)) } - #' @rdname big.matrix #' @export setGeneric('is.readonly', function(x) standardGeneric('is.readonly')) diff --git a/inst/include/bigmemory/MatrixAccessor.hpp b/inst/include/bigmemory/MatrixAccessor.hpp index b6567ee..88efaec 100644 --- a/inst/include/bigmemory/MatrixAccessor.hpp +++ b/inst/include/bigmemory/MatrixAccessor.hpp @@ -20,14 +20,27 @@ class MatrixAccessor _colOffset = 0; _nrow = nrow; } + + MatrixAccessor(T* pData, const index_type &nrow, const index_type &ncol) + { + _pMat = pData; + _totalRows = nrow; + _totalCols = ncol; + _rowOffset = 0; + _colOffset = 0; + _nrow = nrow; + _ncol = ncol; + } MatrixAccessor( BigMatrix &bm ) { _pMat = reinterpret_cast(bm.matrix()); _totalRows = bm.total_rows(); + _totalCols = bm.total_columns(); _rowOffset = bm.row_offset(); _colOffset = bm.col_offset(); _nrow = bm.nrow(); + _ncol = bm.ncol(); } inline T* operator[](const index_type &col) @@ -39,13 +52,20 @@ class MatrixAccessor { return _nrow; } + + index_type ncol() const + { + return _ncol; + } protected: T *_pMat; index_type _totalRows; + index_type _totalCols; index_type _rowOffset; index_type _colOffset; index_type _nrow; + index_type _ncol; }; template @@ -61,6 +81,7 @@ class SepMatrixAccessor _rowOffset = bm.row_offset(); _colOffset = bm.col_offset(); _totalRows = bm.nrow(); + _totalCols = bm.ncol(); } inline T* operator[](const index_type col) @@ -70,7 +91,12 @@ class SepMatrixAccessor index_type nrow() const { - return _nrow; + return _totalRows; + } + + index_type ncol() const + { + return _totalCols; } protected: @@ -78,7 +104,7 @@ class SepMatrixAccessor index_type _rowOffset; index_type _colOffset; index_type _totalRows; - index_type _nrow; + index_type _totalCols; }; #endif //BIG_MATRIX_ACCESSOR diff --git a/man-roxygen/morder_template.R b/man-roxygen/morder_template.R index 5319188..f5e77b4 100644 --- a/man-roxygen/morder_template.R +++ b/man-roxygen/morder_template.R @@ -1,5 +1,5 @@ #' @rdname morder -#' @title Ordering and row-permuting functions for ``big.matrix'' and +#' @title Ordering and Permuting functions for ``big.matrix'' and #' ``matrix'' objects #' @description The \code{morder} function returns a permutation of row #' indices which can be used to rearrangea an object according to the values @@ -9,6 +9,7 @@ #' an order vector or a desired ordering on a set of columns. #' @param x A \code{big.matrix} or \code{matrix} object with numeric values. #' @param cols The columns of \code{x} to get the ordering for or reorder on +#' @param rows The rows of \code{x} to get the ordering for or reorder on #' @param na.last for controlling the treatment of \code{NA}s. If #' \code{TRUE}, missing values in the data are put last; if \code{FALSE}, #' they are put first; if \code{NA}, they are removed. diff --git a/man/morder.Rd b/man/morder.Rd index ce0abdb..42f28de 100644 --- a/man/morder.Rd +++ b/man/morder.Rd @@ -2,13 +2,19 @@ % Please edit documentation in R/bigmemory.R \name{morder} \alias{morder} +\alias{morderCols} \alias{mpermute} -\title{Ordering and row-permuting functions for ``big.matrix'' and +\alias{mpermuteCols} +\title{Ordering and Permuting functions for ``big.matrix'' and ``matrix'' objects} \usage{ morder(x, cols, na.last = TRUE, decreasing = FALSE) +morderCols(x, rows, na.last = TRUE, decreasing = FALSE) + mpermute(x, order = NULL, cols = NULL, allow.duplicates = FALSE, ...) + +mpermuteCols(x, order = NULL, rows = NULL, allow.duplicates = FALSE, ...) } \arguments{ \item{x}{A \code{big.matrix} or \code{matrix} object with numeric values.} @@ -22,6 +28,8 @@ they are put first; if \code{NA}, they are removed.} \item{decreasing}{logical. Should the sort order be increasing or decreasing?} +\item{rows}{The rows of \code{x} to get the ordering for or reorder on} + \item{order}{A vector specifying the reordering of rows, i.e. the result of a call to \code{order} or \code{morder}.} diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 3c47bf1..fcecdbc 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -42,6 +42,43 @@ BEGIN_RCPP return R_NilValue; END_RCPP } +// ReorderRIntMatrixCols +void ReorderRIntMatrixCols(SEXP matrixVector, SEXP nrow, SEXP ncol, SEXP orderVec); +RcppExport SEXP bigmemory_ReorderRIntMatrixCols(SEXP matrixVectorSEXP, SEXP nrowSEXP, SEXP ncolSEXP, SEXP orderVecSEXP) { +BEGIN_RCPP + Rcpp::RNGScope __rngScope; + Rcpp::traits::input_parameter< SEXP >::type matrixVector(matrixVectorSEXP); + Rcpp::traits::input_parameter< SEXP >::type nrow(nrowSEXP); + Rcpp::traits::input_parameter< SEXP >::type ncol(ncolSEXP); + Rcpp::traits::input_parameter< SEXP >::type orderVec(orderVecSEXP); + ReorderRIntMatrixCols(matrixVector, nrow, ncol, orderVec); + return R_NilValue; +END_RCPP +} +// ReorderRNumericMatrixCols +void ReorderRNumericMatrixCols(SEXP matrixVector, SEXP nrow, SEXP ncol, SEXP orderVec); +RcppExport SEXP bigmemory_ReorderRNumericMatrixCols(SEXP matrixVectorSEXP, SEXP nrowSEXP, SEXP ncolSEXP, SEXP orderVecSEXP) { +BEGIN_RCPP + Rcpp::RNGScope __rngScope; + Rcpp::traits::input_parameter< SEXP >::type matrixVector(matrixVectorSEXP); + Rcpp::traits::input_parameter< SEXP >::type nrow(nrowSEXP); + Rcpp::traits::input_parameter< SEXP >::type ncol(ncolSEXP); + Rcpp::traits::input_parameter< SEXP >::type orderVec(orderVecSEXP); + ReorderRNumericMatrixCols(matrixVector, nrow, ncol, orderVec); + return R_NilValue; +END_RCPP +} +// ReorderBigMatrixCols +void ReorderBigMatrixCols(SEXP address, SEXP orderVec); +RcppExport SEXP bigmemory_ReorderBigMatrixCols(SEXP addressSEXP, SEXP orderVecSEXP) { +BEGIN_RCPP + Rcpp::RNGScope __rngScope; + Rcpp::traits::input_parameter< SEXP >::type address(addressSEXP); + Rcpp::traits::input_parameter< SEXP >::type orderVec(orderVecSEXP); + ReorderBigMatrixCols(address, orderVec); + return R_NilValue; +END_RCPP +} // OrderRIntMatrix SEXP OrderRIntMatrix(SEXP matrixVector, SEXP nrow, SEXP columns, SEXP naLast, SEXP decreasing); RcppExport SEXP bigmemory_OrderRIntMatrix(SEXP matrixVectorSEXP, SEXP nrowSEXP, SEXP columnsSEXP, SEXP naLastSEXP, SEXP decreasingSEXP) { @@ -86,6 +123,52 @@ BEGIN_RCPP return __result; END_RCPP } +// OrderRIntMatrixCols +SEXP OrderRIntMatrixCols(SEXP matrixVector, SEXP nrow, SEXP ncol, SEXP rows, SEXP naLast, SEXP decreasing); +RcppExport SEXP bigmemory_OrderRIntMatrixCols(SEXP matrixVectorSEXP, SEXP nrowSEXP, SEXP ncolSEXP, SEXP rowsSEXP, SEXP naLastSEXP, SEXP decreasingSEXP) { +BEGIN_RCPP + Rcpp::RObject __result; + Rcpp::RNGScope __rngScope; + Rcpp::traits::input_parameter< SEXP >::type matrixVector(matrixVectorSEXP); + Rcpp::traits::input_parameter< SEXP >::type nrow(nrowSEXP); + Rcpp::traits::input_parameter< SEXP >::type ncol(ncolSEXP); + Rcpp::traits::input_parameter< SEXP >::type rows(rowsSEXP); + Rcpp::traits::input_parameter< SEXP >::type naLast(naLastSEXP); + Rcpp::traits::input_parameter< SEXP >::type decreasing(decreasingSEXP); + __result = Rcpp::wrap(OrderRIntMatrixCols(matrixVector, nrow, ncol, rows, naLast, decreasing)); + return __result; +END_RCPP +} +// OrderRNumericMatrixCols +SEXP OrderRNumericMatrixCols(SEXP matrixVector, SEXP nrow, SEXP ncol, SEXP rows, SEXP naLast, SEXP decreasing); +RcppExport SEXP bigmemory_OrderRNumericMatrixCols(SEXP matrixVectorSEXP, SEXP nrowSEXP, SEXP ncolSEXP, SEXP rowsSEXP, SEXP naLastSEXP, SEXP decreasingSEXP) { +BEGIN_RCPP + Rcpp::RObject __result; + Rcpp::RNGScope __rngScope; + Rcpp::traits::input_parameter< SEXP >::type matrixVector(matrixVectorSEXP); + Rcpp::traits::input_parameter< SEXP >::type nrow(nrowSEXP); + Rcpp::traits::input_parameter< SEXP >::type ncol(ncolSEXP); + Rcpp::traits::input_parameter< SEXP >::type rows(rowsSEXP); + Rcpp::traits::input_parameter< SEXP >::type naLast(naLastSEXP); + Rcpp::traits::input_parameter< SEXP >::type decreasing(decreasingSEXP); + __result = Rcpp::wrap(OrderRNumericMatrixCols(matrixVector, nrow, ncol, rows, naLast, decreasing)); + return __result; +END_RCPP +} +// OrderBigMatrixCols +SEXP OrderBigMatrixCols(SEXP address, SEXP rows, SEXP naLast, SEXP decreasing); +RcppExport SEXP bigmemory_OrderBigMatrixCols(SEXP addressSEXP, SEXP rowsSEXP, SEXP naLastSEXP, SEXP decreasingSEXP) { +BEGIN_RCPP + Rcpp::RObject __result; + Rcpp::RNGScope __rngScope; + Rcpp::traits::input_parameter< SEXP >::type address(addressSEXP); + Rcpp::traits::input_parameter< SEXP >::type rows(rowsSEXP); + Rcpp::traits::input_parameter< SEXP >::type naLast(naLastSEXP); + Rcpp::traits::input_parameter< SEXP >::type decreasing(decreasingSEXP); + __result = Rcpp::wrap(OrderBigMatrixCols(address, rows, naLast, decreasing)); + return __result; +END_RCPP +} // CCleanIndices SEXP CCleanIndices(SEXP indices, SEXP rc); RcppExport SEXP bigmemory_CCleanIndices(SEXP indicesSEXP, SEXP rcSEXP) { diff --git a/src/bigmemory.cpp b/src/bigmemory.cpp index 8304f54..5aa1ad1 100644 --- a/src/bigmemory.cpp +++ b/src/bigmemory.cpp @@ -913,6 +913,33 @@ void reorder_matrix( MatrixAccessorType m, SEXP orderVec, } } +// Function to reorder columns +// It likely could use improvement as it just goes element by element +// Added 9-17-2015 by Charles Determan +template +void reorder_matrix2( MatrixAccessorType m, SEXP orderVec, + index_type numRows, FileBackedBigMatrix *pfbm ) +{ + double *pov = NUMERIC_DATA(orderVec); + typedef typename MatrixAccessorType::value_type ValueType; + typedef std::vector Values; + Values vs(m.ncol()); + index_type i,j; + + for (j=0; j < numRows; ++j) + { + for (i=0; i < m.ncol(); ++i) + { + vs[i] = m[static_cast(pov[i])-1][j]; + } + for(i = 0; i < m.ncol(); ++i) + { + m[i][j] = vs[i]; + } + if (pfbm) pfbm->flush(); + } +} + template SEXP get_order( MatrixAccessorType m, SEXP columns, SEXP naLast, SEXP decreasing ) @@ -1002,6 +1029,95 @@ SEXP get_order( MatrixAccessorType m, SEXP columns, SEXP naLast, return ret; } +template +SEXP get_order2( MatrixAccessorType m, SEXP rows, SEXP naLast, + SEXP decreasing ) +{ + typedef typename MatrixAccessorType::value_type ValueType; + typedef typename std::pair PairType; + typedef std::vector OrderVecs; + std::size_t i; + index_type k; + index_type row; + OrderVecs ov; + ov.reserve(m.ncol()); + typename OrderVecs::iterator begin, end, it, naIt; + ValueType val; + for (k=GET_LENGTH(rows)-1; k >= 0; --k) + { + row = static_cast(NUMERIC_DATA(rows)[k]-1); + if (k==GET_LENGTH(rows)-1) + { + if (isna(INTEGER_VALUE(naLast))) + { + for (i=0; i < static_cast(m.ncol()); ++i) + { + val = m[row][i]; + if (!isna(val)) + { + ov.push_back( std::make_pair( static_cast(i), val) ); + } + } + } + else + { + ov.resize(m.ncol()); + for (i=0; i < static_cast(m.ncol()); ++i) + { + val = m[i][row]; + ov[i].first = i; + ov[i].second = val; + } + } + } + else // not the first column we've looked at + { + if (isna(INTEGER_VALUE(naLast))) + { + i=0; + while (i < ov.size()) + { + val = m[static_cast(ov[i].first)][row]; + if (!isna(val)) + { + ov[i++].second = val; + } + else + { + ov.erase(ov.begin()+i); + } + } + } + else + { + for (i=0; i < static_cast(m.ncol()); ++i) + { + ov[i].second = m[static_cast(ov[i].first)][row]; + } + } + } + if (LOGICAL_VALUE(decreasing) == 0) + { + std::stable_sort(ov.begin(), ov.end(), + SecondLess(INTEGER_VALUE(naLast)) ); + } + else + { + std::stable_sort(ov.begin(), ov.end(), + SecondGreater(INTEGER_VALUE(naLast))); + } + } + + SEXP ret = PROTECT(NEW_NUMERIC(ov.size())); + double *pret = NUMERIC_DATA(ret); + for (i=0, it=ov.begin(); it < ov.end(); ++it, ++i) + { + pret[i] = it->first+1; + } + UNPROTECT(1); + return ret; +} + // Rcpp Functions @@ -1072,6 +1188,75 @@ void ReorderBigMatrix( SEXP address, SEXP orderVec ) } } +// [[Rcpp::export]] +void ReorderRIntMatrixCols( SEXP matrixVector, SEXP nrow, SEXP ncol, SEXP orderVec ) +{ + return reorder_matrix2( + MatrixAccessor(INTEGER_DATA(matrixVector), + static_cast(INTEGER_VALUE(nrow)), + static_cast(INTEGER_VALUE(ncol))), orderVec, + static_cast(INTEGER_VALUE(nrow)), NULL ); +} + +// [[Rcpp::export]] +void ReorderRNumericMatrixCols( SEXP matrixVector, SEXP nrow, SEXP ncol, + SEXP orderVec ) +{ + return reorder_matrix2( + MatrixAccessor(NUMERIC_DATA(matrixVector), + static_cast(INTEGER_VALUE(nrow)), + static_cast(INTEGER_VALUE(ncol))), orderVec, + static_cast(INTEGER_VALUE(nrow)), NULL ); +} + +// [[Rcpp::export]] +void ReorderBigMatrixCols( SEXP address, SEXP orderVec ) +{ + BigMatrix *pMat = reinterpret_cast(R_ExternalPtrAddr(address)); + if (pMat->separated_columns()) + { + switch (pMat->matrix_type()) + { + case 1: + return reorder_matrix2( SepMatrixAccessor(*pMat), orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + case 2: + return reorder_matrix2( SepMatrixAccessor(*pMat), orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + case 4: + return reorder_matrix2( SepMatrixAccessor(*pMat),orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + case 6: + return reorder_matrix2( SepMatrixAccessor(*pMat),orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + case 8: + return reorder_matrix2( SepMatrixAccessor(*pMat),orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + } + } + else + { + switch (pMat->matrix_type()) + { + case 1: + return reorder_matrix2( MatrixAccessor(*pMat),orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + case 2: + return reorder_matrix2( MatrixAccessor(*pMat),orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + case 4: + return reorder_matrix2( MatrixAccessor(*pMat),orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + case 6: + return reorder_matrix2( MatrixAccessor(*pMat),orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + case 8: + return reorder_matrix2( MatrixAccessor(*pMat),orderVec, + pMat->nrow(), dynamic_cast(pMat) ); + } + } +} + // [[Rcpp::export]] SEXP OrderRIntMatrix( SEXP matrixVector, SEXP nrow, SEXP columns, SEXP naLast, SEXP decreasing ) @@ -1141,6 +1326,78 @@ SEXP OrderBigMatrix(SEXP address, SEXP columns, SEXP naLast, SEXP decreasing) return R_NilValue; } +// [[Rcpp::export]] +SEXP OrderRIntMatrixCols( SEXP matrixVector, SEXP nrow, SEXP ncol, + SEXP rows, SEXP naLast, SEXP decreasing ) +{ + return get_order2( + MatrixAccessor(INTEGER_DATA(matrixVector), + static_cast(INTEGER_VALUE(nrow)), + static_cast(INTEGER_VALUE(ncol))), + rows, naLast, decreasing ); +} + +// [[Rcpp::export]] +SEXP OrderRNumericMatrixCols( SEXP matrixVector, SEXP nrow, SEXP ncol, + SEXP rows, SEXP naLast, SEXP decreasing ) +{ + return get_order2( + MatrixAccessor(NUMERIC_DATA(matrixVector), + static_cast(INTEGER_VALUE(nrow)), + static_cast(INTEGER_VALUE(ncol))), + rows, naLast, decreasing ); +} + +// [[Rcpp::export]] +SEXP OrderBigMatrixCols(SEXP address, SEXP rows, +SEXP naLast, SEXP decreasing) +{ + BigMatrix *pMat = reinterpret_cast(R_ExternalPtrAddr(address)); + if (pMat->separated_columns()) + { + switch (pMat->matrix_type()) + { + case 1: + return get_order2( SepMatrixAccessor(*pMat), + rows, naLast, decreasing ); + case 2: + return get_order2( SepMatrixAccessor(*pMat), + rows, naLast, decreasing ); + case 4: + return get_order2( SepMatrixAccessor(*pMat), + rows, naLast, decreasing ); + case 6: + return get_order2( SepMatrixAccessor(*pMat), + rows, naLast, decreasing ); + case 8: + return get_order2( SepMatrixAccessor(*pMat), + rows, naLast, decreasing ); + } + } + else + { + switch (pMat->matrix_type()) + { + case 1: + return get_order2( MatrixAccessor(*pMat), + rows, naLast, decreasing ); + case 2: + return get_order2( MatrixAccessor(*pMat), + rows, naLast, decreasing ); + case 4: + return get_order2( MatrixAccessor(*pMat), + rows, naLast, decreasing ); + case 6: + return get_order2( MatrixAccessor(*pMat), + rows, naLast, decreasing ); + case 8: + return get_order2( MatrixAccessor(*pMat), + rows, naLast, decreasing ); + } + } + return R_NilValue; +} + // [[Rcpp::export]] SEXP CCleanIndices(SEXP indices, SEXP rc) { diff --git a/tests/testthat/test_morder.R b/tests/testthat/test_morder.R index 8f14dc7..65226df 100644 --- a/tests/testthat/test_morder.R +++ b/tests/testthat/test_morder.R @@ -4,6 +4,11 @@ context("morder/mpermute") m = matrix(as.double(as.matrix(iris[,1:4])), nrow=nrow(iris[,1:4])) n = m +mm <- m[1:4,1:4] +colnames(mm) <- letters[1:4] +bm <- as.big.matrix(mm) + + test_that("morder equivalent to order",{ expect_identical(morder(m, 1), as.numeric(order(m[,1]))) }) @@ -12,3 +17,22 @@ test_that("mpermute changes elements order",{ expect_false(all(m == mpermute(m, cols=1))) expect_true(all(n == m[morder(m,1),])) }) + +test_that("column reording works", { + mpermuteCols(bm, order = c(3,4,1,2)) + expect_equivalent(bm[], mm[,c('c','d','a','b')]) + mpermuteCols(mm, order = c(3,4,1,2)) + expect_equivalent(bm[], mm) + mpermuteCols(bm, rows = 1) + mpermuteCols(mm, rows = 1) + expect_equivalent(bm[], mm) +}) + +test_that("morderCols works",{ + expect_true(all(order(mm[1,]) == morderCols(bm, rows = 1))) + expect_true(all(order(mm[2,]) == morderCols(mm, rows = 2))) +}) + +rm(bm) +gc() +