R/tatami-utils.R

Defines functions tatami.multiply tatami.realize tatami.prefer.rows tatami.is.sparse tatami.column.sums tatami.row.sums tatami.column tatami.row tatami.dim tatami.binary tatami.not tatami.math tatami.log tatami.round tatami.logic tatami.compare tatami.arith tatami.subset tatami.transpose tatami.bind

Documented in tatami.arith tatami.binary tatami.bind tatami.column tatami.column.sums tatami.compare tatami.dim tatami.is.sparse tatami.log tatami.logic tatami.math tatami.multiply tatami.not tatami.prefer.rows tatami.realize tatami.round tatami.row tatami.row.sums tatami.subset tatami.transpose

#' Tatami utilities
#'
#' Utility functions that directly operate on the pointers produced by \code{\link{initializeCpp}}.
#' Some of these are used internally by \code{initializeCpp} methods operating on \pkg{DelayedArray} classes.
#'
#' @param x A pointer produced by \code{\link{initializeCpp}}.
#' @param xs A list of pointers produced by \code{\link{initializeCpp}}.
#' All matrices should have the same number of rows (if \code{by.row=FALSE}) or columns (otherwise).
#' @param by.row Logical scalar indicating whether to apply the operation on the rows.
#' \itemize{
#' \item For \code{tatami.bind}, this will combine the matrices by rows,
#' i.e., the output matrix has a number of rows equal to the sum of the number of rows in \code{xs}.
#' \item For \code{tatami.subset}, this will subset the matrix by row.
#' \item For \code{tatami.arith}, \code{tatami.compare} and \code{tatami.logic} with a vector \code{val},
#' the vector should have length equal to the number of rows.k
#' }
#' @param op String specifying the operation to perform.
#' \itemize{
#' \item For \code{tatami.arith}, this should be one of the operations in \link{Arith}.
#' \item For \code{tatami.compare}, this should be one of the operations in \link{Compare}.
#' \item For \code{tatami.logic}, this should be one of the operations in \link{Logic}.
#' \item For \code{tatami.math}, this should be one of the operations in \link{Math}.
#' \item For \code{tatami.binary}, this may be any operation in \link{Arith}, \link{Compare} or \link{Logic}.
#' }
#' @param val For \code{tatami.arith}, \code{tatami.compare} and \code{tatami.logic}, the value to be used in the operation specified by \code{op}. 
#' This may be a:
#' \itemize{
#' \item Numeric scalar, which is used in the operation for all entries of the matrix.
#' \item Numeric vector of length equal to the number of rows, where each value is used in the operation with the corresponding row when \code{by.row=TRUE}.
#' \item Numeric vector of length equal to the number of column, where each value is used with the corresponding column when \code{by.row=FALSE}.
#' }
#'
#' For \code{tatami.multiply}, the value to be used in the matrix multiplication.
#' This may be a:
#' \itemize{
#' \item Numeric vector of length equal to the number of columns of \code{x} (if \code{right=FALSE}) or rows (otherwise).
#' \item Numeric matrix with number of rows equal to the number of columns of \code{x} (if \code{right=FALSE}) or rows (otherwise).
#' \item Pointer produced by \code{\link{initializeCpp}}, 
#' referencing a matrix with number of rows equal to the number of columns of \code{x} (if \code{right=FALSE}) or rows (otherwise).
#' }
#' @param right For \code{tatami.arith} and \code{tatami.compare}, 
#' a logical scalar indicating that \code{val} is on the right-hand side of the operation.
#'
#' For \code{tatami.multiply}, a logical scalar indicating that \code{val} is on the right-hand side of the multiplication.
#' @param subset Integer vector containing the subset of interest.
#' These should be 1-based row or column indices depending on \code{by.row}.
#' @param y A pointer produced by \code{\link{initializeCpp}},
#' referencing a matrix of the same dimensions as \code{x}.
#' @param base Numeric scalar specifying the base of the log-transformation.
#' @param i Integer scalar containing the 1-based index of the row (for \code{tatami.row}) or column (for \code{tatami.column}) of interest. 
#' @param num.threads Integer scalar specifying the number of threads to use.
#'
#' @return 
#' For \code{tatami.dim}, an integer vector containing the dimensions of the matrix.
#'
#' For \code{tatami.is.sparse}, a logical scalar indicating whether the matrix is sparse.
#'
#' For \code{tatami.prefer.rows}, a logical scalar indicating whether the matrix prefers iteration by row.
#'
#' For \code{tatami.row} or \code{tatami.column}, a numeric vector containing the contents of row or column \code{i}, respectively.
#'
#' For \code{tatami.row.sums} or \code{tatami.column.sums}, a numeric vector containing the row or column sums, respectively.
#'
#' For \code{tatami.realize}, a numeric matrix or \linkS4class{dgCMatrix} with the matrix contents.
#' The exact class depends on whether \code{x} refers to a sparse matrix. 
#' 
#' For \code{tatami.multiply}, a numeric matrix containing the matrix product of \code{x} and \code{other}.
#' 
#' For all other functions, a new pointer to a matrix with the requested operations applied to \code{x} or \code{xs}.
#'
#' @author Aaron Lun
#' @examples
#' x <- Matrix::rsparsematrix(1000, 100, 0.1)
#' ptr <- initializeCpp(x)
#' tatami.dim(ptr)
#' tatami.row(ptr, 1)
#'
#' rounded <- tatami.round(ptr)
#' tatami.row(rounded, 1)
#'
#' @name tatami-utils
NULL

#' @export
#' @rdname tatami-utils
tatami.bind <- function(xs, by.row) { 
    apply_delayed_bind(xs, by.row)
}

#' @export
#' @rdname tatami-utils
tatami.transpose <- function(x) {
    apply_delayed_transpose(x)
}

#' @export
#' @rdname tatami-utils
tatami.subset <- function(x, subset, by.row) {
    apply_delayed_subset(x, subset, by.row)
}

#' @export
#' @rdname tatami-utils
tatami.arith <- function(x, op, val, by.row, right) {
    if (op %in% supported.Arith1) {
        apply_delayed_associative_arithmetic(x, val, by.row, op)
    } else if (op %in% supported.Arith2) {
        apply_delayed_nonassociative_arithmetic(x, val, right, by.row, op)
    } else {
        stop("unknown operation '", op, "'")
    }
}

#' @export
#' @rdname tatami-utils
tatami.compare <- function(x, op, val, by.row, right) {
    op <- match.arg(op, supported.Compare)
    if (!right) { # need to flip the operation if the argument is not on the right.
        op <- reverse.Compare[[op]]
    }
    apply_delayed_comparison(x, val, by.row, op)
}

#' @export
#' @rdname tatami-utils
tatami.logic <- function(x, op, val, by.row) {
    op <- match.arg(op, supported.Logic)
    apply_delayed_boolean(x, val, by.row, op)
}

#' @export
#' @rdname tatami-utils
tatami.round <- function(x) {
    apply_delayed_round(x)
}

#' @export
#' @rdname tatami-utils
tatami.log <- function(x, base) {
    apply_delayed_log(x, base)
}

#' @export
#' @rdname tatami-utils
tatami.math <- function(x, op) {
    apply_delayed_unary_math(x, op)
}

#' @export
#' @rdname tatami-utils
tatami.not <- function(x) {
    apply_delayed_boolean_not(x)
}

#' @export
#' @rdname tatami-utils
tatami.binary <- function(x, y, op) {
    op <- match.arg(op, supported.Ops)
    apply_delayed_binary_operation(x, y, op)
}

#' @export
#' @rdname tatami-utils
tatami.dim <- function(x) {
    tatami_dim(x)
}

#' @export
#' @rdname tatami-utils
tatami.row <- function(x, i) {
    tatami_row(x, i)
}

#' @export
#' @rdname tatami-utils
tatami.column <- function(x, i) {
    tatami_column(x, i)
}

#' @export
#' @rdname tatami-utils
tatami.row.sums <- function(x, num.threads) {
    tatami_row_sums(x, num.threads)
}

#' @export
#' @rdname tatami-utils
tatami.column.sums <- function(x, num.threads) {
    tatami_column_sums(x, num.threads)
}

#' @export
#' @rdname tatami-utils
tatami.is.sparse <- function(x) {
    tatami_is_sparse(x)
}

#' @export
#' @rdname tatami-utils
tatami.prefer.rows <- function(x) {
    tatami_prefer_rows(x)
}

#' @export
#' @rdname tatami-utils
tatami.realize <- function(x, num.threads) {
    tatami_realize(x, num.threads)
}

#' @export
#' @rdname tatami-utils
tatami.multiply <- function(x, val, right, num.threads) {
    if (is.atomic(val)) {
        if (is.null(dim(val))) {
            tatami_multiply_vector(x, val, right=right, num_threads=num.threads)
        } else if (!right) {
            t(tatami_multiply_columns(x, t(val), right=right, num_threads=num.threads))
        } else {
            tatami_multiply_columns(x, val, right=right, num_threads=num.threads)
        }
    } else {
        tatami_multiply_matrix(x, val, right=right, num_threads=num.threads)
    }
}
LTLA/beachmat documentation built on Nov. 15, 2024, 10:19 p.m.