Skip to content

Commit 3fabf36

Browse files
committed
implement matrix multiplication, closes #226
1 parent 5f17332 commit 3fabf36

File tree

5 files changed

+63
-34
lines changed

5 files changed

+63
-34
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* Add `scale_{type}_units()` scales for additional continuous aesthetics
1010
(colour, fill, alpha, size, linewidth); #369
1111

12+
* Implement `matrixOps.units`, with support for `%*%` (R >= 4.3.0); #226
13+
1214
# version 0.8-7
1315

1416
* Deep copy of `ud_convert()` input to avoid side effects; #403

R/arith.R

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -200,34 +200,30 @@ Ops.units <- function(e1, e2) {
200200
.as.units(NextMethod(), u)
201201
}
202202

203-
#' #' matrix multiplication
204-
#' #' @name matmult
205-
#' #' @param x numeric matrix or vector
206-
#' #' @param y numeric matrix or vector
207-
#' #' @export
208-
#' #' @details see \code{"\link[base]{\%*\%}"} for the base function, reimplemented
209-
#' #' as default method
210-
#' `%*%` = function(x, y) UseMethod("%*%")
203+
#' S3 matrixOps Group Generic Functions for units objects
211204
#'
212-
#' #' @name matmult
213-
#' #' @export
214-
#' `%*%.default` = function(x, y) {
215-
#' if (inherits(y, "units"))
216-
#' `%*%.units`(x, y)
217-
#' else
218-
#' base::`%*%`(x, y)
219-
#' }
205+
#' matrixOps functions for units objects.
220206
#'
221-
#' #' @name matmult
222-
#' #' @export
223-
#' #' @examples
224-
#' #' a = set_units(1:5, m)
225-
#' #' a %*% a
226-
#' #' a %*% t(a)
227-
#' #' a %*% set_units(1:5, 1)
228-
#' #' set_units(1:5, 1) %*% a
229-
#' `%*%.units` = function(x, y) {
230-
#' ret = `%*%.default`(unclass(x), unclass(y))
231-
#' units(ret) = .multiply_symbolic_units(1, units(x), units(y))
232-
#' ret
233-
#' }
207+
#' @param x object of class \code{units},
208+
#' or something that can be coerced to it by \code{as_units(x)}
209+
#' @param y object of class \code{units},
210+
#' or something that can be coerced to it by \code{as_units(y)}
211+
#'
212+
#' @return object of class \code{units}
213+
#'
214+
#' @examples
215+
#' a = set_units(1:5, m)
216+
#' a %*% a
217+
#' a %*% t(a)
218+
#' a %*% 1:5
219+
#' 1:5 %*% a
220+
matrixOps.units <- function(x, y) {
221+
mul <- .Generic %in% c("%*%") # multiplication-only
222+
223+
if (! any(mul))
224+
stop(paste("operation", .Generic, "not allowed"))
225+
226+
u <- units(x[0] * y[0])
227+
.as.units(NextMethod(), u)
228+
}
229+
# registered .onLoad

R/init.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ NULL
1818
ud_set_encoding(native)
1919

2020
register_all_s3_methods()
21+
if (exists("matrixOps"))
22+
registerS3method("matrixOps", "units", matrixOps.units)
2123
}
2224

2325
.onAttach <- function(libname, pkgname) {

man/matrixOps.units.Rd

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test_arith.R

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,12 @@ test_that("%/% and %% work", {
208208
expect_true(all(x %% y >= set_units(0, m^2)))
209209
})
210210

211-
#test_that("%*% work", {
212-
# mat = set_units(matrix(1:5, 1), m)
213-
# expect_equal(mat %*% t(mat), set_units(matrix(55), m^2))
214-
# expect_equal(t(mat) %*% mat, set_units(t(unclass(mat)) %*% unclass(mat), m^2))
215-
#})
211+
test_that("%*% work", {
212+
skip_if_not_installed("base", "4.3.0")
213+
mat = set_units(matrix(1:5, 1), m)
214+
expect_equal(mat %*% t(mat), set_units(matrix(55), m^2))
215+
expect_equal(t(mat) %*% mat, set_units(t(unclass(mat)) %*% unclass(mat), m^2))
216+
})
216217

217218
test_that("The order of multiplication for basic units is commutative", {
218219
a <- set_units(1:4, m^-3)

0 commit comments

Comments
 (0)