r-lib / rray

Simple Arrays
https://rray.r-lib.org
GNU General Public License v3.0
130 stars 12 forks source link

Remove `rray_det()` #223

Closed DavisVaughan closed 5 years ago

DavisVaughan commented 5 years ago

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)

DavisVaughan commented 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))
}
DavisVaughan commented 5 years ago
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)))
})