Closed DavisVaughan closed 5 years ago
Holding onto current implementation for potential future use
#' Compute the determinant
#'
#' `rray_det()` computes the determinant of a matrix.
#'
#' @param x A square matrix to compute the determinant for.
#' Alternatively, a higher dimensional array which is treated as a stack
#' of matrices computed from the first two dimensions.
#'
#' @examples
#' x <- matrix(1:4, ncol = 2)
#'
#' # Dimensions are kept
#' rray_det(x)
#'
#' x_3d <- rray_broadcast(x, c(2, 2, 3))
#'
#' # 3D matrices are treated as stacks of 2D matrices
#' rray_det(x_3d)
#'
#' @export
rray_det <- function(x) {
dim_n <- rray_dim_n(x)
if (dim_n < 2) {
glubort(
"Cannot compute the determinant of a {rray_dim_n(x)}D object."
)
}
if (dim_n == 2L) {
x_split <- list(x)
}
else {
# non matrix axes, split in (correct) reverse order
axes <- rev(seq_len(dim_n)[-c(1L ,2L)])
x_split <- rray_split(x, axes)
}
res <- map_dbl(x_split, rray_det_single)
res <- keep_dims(res, x, c(1L, 2L))
new_dim_names <- rray_resize_dim_names(rray_dim_names(x), rray_dim(res))
res <- rray_set_dim_names(res, new_dim_names)
vec_cast_container(res, x)
}
rray_det_single <- function(x) {
det(as_matrix(x))
}
context("test-det")
test_that("can compute the determinant of a matrix", {
x <- matrix(c(2, 3, 4, 1), nrow = 2)
expect_equal(as_matrix(det(x)), rray_det(x))
})
test_that("computing the determinant doesn't drop dimensionality", {
x <- matrix(c(2, 3, 4, 1), nrow = 2)
expect_equal(vec_dim(rray_det(x)), c(1, 1))
})
test_that("can compute the determinant of sub matrices in an array", {
x <- array(c(2, 3, 4, 1, 2, 4, 6, 8), c(2, 2, 2))
expect_equal(vec_dim(rray_det(x)), c(1, 1, 2))
expect_equal(rray_det(x), new_array(c(-10, -8), c(1, 1, 2)))
})
As I don't think rray will be much about providing linear algebra (besides providing the
rray_dot()
wrapper so it will at least work right)