#' Computes the density of a multivariate normal distribution
#' @param x vector or matrix of values for which the density is computed.
#' If \code{x} is a vector, it represents a single draw.
#' If \code{x} is a matrix, each row is taken to be a single draw.
#' @param mean mean vector
#' @param sigma covariance matrix
#' @param log logical indicating whether to return on the log scale or not.
#' False by default.
#' @return Densities of the draws x.
#' @export
dmvnorm <- function(x, mean, sigma, log = FALSE) {
checkmate::assertNumeric(mean, any.missing = FALSE, min.len = 2)
checkmate::assertMatrix(sigma, any.missing = FALSE, min.rows = 2, min.cols = 2)
checkmate::assert(dim(sigma)[1] == dim(sigma)[2],
.var.name = 'check that covariance matrix is square')
checkmate::assert(dim(sigma)[1] == length(mean),
.var.name = 'check that mean vector and covariance matrix have matching sizes')
checkmate::assertLogical(log, len = 1)
checkmate::assert(checkmate::checkMatrix(x),checkmate::checkVector(x))
if (class(x) == "matrix") {
checkmate::assert(dim(x)[2] == length(mean),
.var.name = 'check that x has correct dimensions')
}
else if (class(x) == "numeric") {
checkmate::assert(length(x) == length(mean),
.var.name = 'check that x has correct length')
}
if (is.vector(x))
x <- matrix(x, ncol = length(x))
cholesky <- chol(sigma)
tmp <- backsolve(cholesky, t(x) - mean, transpose = TRUE)
xMx <- colSums(tmp ^ 2)
ret <- - 0.5 * (ncol(x) * log(2 * pi) + 2* sum(log(diag(cholesky))) + xMx)
if (log) {
ret
}
else {
exp(ret)
}
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.