-
Notifications
You must be signed in to change notification settings - Fork 13
Add matrix, array and matrix multiplication for integer64 #195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b40f6c1
e781e13
400fb45
d9e0f7d
6421d8e
0777b57
e48e746
c6aa44f
df8a02d
58532f2
b334ccd
c3245d1
63a394c
c765dac
2ba1592
98220d3
b65c95d
4604631
d72712e
ccea4aa
f7b3c7a
8f685a0
8382964
7cff847
1c623b0
b6bf9fe
71d0763
c49fafe
621dc27
67bf8f3
828ca3c
f132dc5
9ba6447
05b7796
e70687d
4135218
a53f096
abaa1d5
a59e5af
1b1769f
6fc7b68
dd1eefd
2474aff
f1ed4ce
d278649
eef6a7c
f6dfc1a
ad2bb9f
30c86e0
204e200
3377e6d
9c7b2f2
84acaf7
959cb49
91c15b3
a8439c0
76e9beb
70eae32
cbe9f75
3bee116
c8db889
23da2df
44441db
b622074
073cd30
f4d5308
5a06955
ff054ab
1f3e934
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,64 +19,136 @@ | |
| #' @param x An array of integer64 numbers. | ||
| #' @param na.rm,dims Same interpretation as in [colSums()]. | ||
| #' @param ... Passed on to subsequent methods. | ||
| #' @param data,nrow,ncol,byrow,dimnames,dim Arguments for `matrix()` and `array()`. | ||
| #' @examples | ||
| #' A = as.integer64(1:6) | ||
| #' dim(A) = 3:2 | ||
| #' A = matrix(as.integer64(1:6), 3) | ||
| #' | ||
| #' colSums(A) | ||
| #' rowSums(A) | ||
| #' aperm(A, 2:1) | ||
| #' @name matrix64 | ||
| NULL | ||
|
|
||
| #' @rdname matrix64 | ||
| #' @export | ||
| colSums = function(x, na.rm=FALSE, dims=1L) UseMethod("colSums") | ||
| #' @rdname matrix64 | ||
| #' @export | ||
| colSums.default = function(x, na.rm=FALSE, dims=1L) base::colSums(x, na.rm, dims) | ||
|
|
||
| #' @rdname matrix64 | ||
| #' @export | ||
| colSums.integer64 = function(x, na.rm=FALSE, dims=1L) { | ||
| n_dim = length(dim(x)) | ||
| stopifnot( | ||
| `dims= should be a length-1 integer between 1 and length(dim(x))-1L` = | ||
| length(dims) == 1L && dims > 0L && dims < n_dim | ||
| ) | ||
| MARGIN = tail(seq_len(n_dim), -dims) | ||
| ret = apply(x, MARGIN, sum, na.rm = na.rm) | ||
| class(ret) = "integer64" | ||
| #' @exportS3Method matrix integer64 | ||
| matrix.integer64 = function(data=NA_integer64_, ...) { | ||
| if (!length(data)) data = NA_integer64_ | ||
| ret = withCallingHandlers_and_choose_call( | ||
| base::matrix(data=data, ...), | ||
| c("matrix", "matrix.integer64") | ||
| ) | ||
| class(ret) = class(data) | ||
| ret | ||
| } | ||
|
|
||
| #' @rdname matrix64 | ||
| #' @export | ||
| rowSums = function(x, na.rm=FALSE, dims=1L) UseMethod("rowSums") | ||
| #' @exportS3Method array integer64 | ||
| array.integer64 = function(data=NA_integer64_, ...) { | ||
| if (!length(data)) data = NA_integer64_ | ||
| ret = withCallingHandlers_and_choose_call( | ||
| base::array(data=data, ...), | ||
| c("array", "array.integer64") | ||
| ) | ||
| class(ret) = class(data) | ||
| ret | ||
| } | ||
|
|
||
| #' @rdname matrix64 | ||
| #' @export | ||
| rowSums.default = function(x, na.rm=FALSE, dims=1L) base::rowSums(x, na.rm, dims) | ||
| colSums.integer64 = function(x, na.rm=FALSE, dims=1L) { | ||
| dn = dim(x) | ||
| if (!is.array(x) || length(dn) < 2L) | ||
| stop(errorCondition(gettext("'x' must be an array of at least two dimensions", domain="R-base"), call=choose_sys_call(c("colSums", "colSums.integer64")))) | ||
| if (length(dims) != 1L || dims < 1L || dims > length(dn) - 1L) | ||
| stop(errorCondition(gettext("invalid 'dims'", domain="R-base"), call=choose_sys_call(c("colSums", "colSums.integer64")))) | ||
|
|
||
| ret = apply(x, seq_along(dn)[-seq_len(dims)], sum, na.rm=na.rm) | ||
| class(ret) = class(x) | ||
| ret | ||
| } | ||
|
|
||
| #' @rdname matrix64 | ||
| #' @export | ||
| rowSums.integer64 = function(x, na.rm=FALSE, dims=1L) { | ||
| n_dim = length(dim(x)) | ||
| stopifnot( | ||
| `dims= should be a length-1 integer between 1 and length(dim(x))-1L` = | ||
| length(dims) == 1L && dims > 0L && dims < n_dim | ||
| ) | ||
| MARGIN = seq_len(dims) | ||
| ret = apply(x, MARGIN, sum, na.rm = na.rm) | ||
| class(ret) = "integer64" | ||
| dn = dim(x) | ||
| if (!is.array(x) || length(dn) < 2L) | ||
| stop(errorCondition(gettext("'x' must be an array of at least two dimensions", domain="R-base"), call=choose_sys_call(c("rowSums", "rowSums.integer64")))) | ||
| if (length(dims) != 1L || dims < 1L || dims > length(dn) - 1L) | ||
| stop(errorCondition(gettext("invalid 'dims'", domain="R-base"), call=choose_sys_call(c("rowSums", "rowSums.integer64")))) | ||
|
|
||
| ret = apply(x, seq_len(dims), sum, na.rm=na.rm) | ||
| class(ret) = class(x) | ||
| ret | ||
| } | ||
|
|
||
| #' @rdname matrix64 | ||
| #' @param a,perm Passed on to [aperm()]. | ||
| #' @export | ||
| #' @exportS3Method base::aperm integer64 | ||
| aperm.integer64 = function(a, perm, ...) { | ||
| class(a) = minusclass(class(a), "integer64") | ||
| ret = aperm(a, perm, ...) | ||
| class(ret) = plusclass(class(a), "integer64") | ||
| ret = NextMethod() | ||
| class(ret) = class(a) | ||
| ret | ||
| } | ||
|
|
||
| #' @exportS3Method base::`%*%` integer64 | ||
| `%*%.integer64` = function(x, y) { | ||
| if (!is.integer64(x) && !is.integer64(y)) | ||
| return(x%*%y) | ||
|
|
||
| target_class = target_class_for_Ops(x, y) | ||
| if (target_class != "integer64") { | ||
| if (is.integer64(x)) { | ||
| for (cc in class(y)) { | ||
| f = getS3method("%*%", cc, optional=TRUE) | ||
| if (!is.null(f)) | ||
| return(f(.as_double_integer64(x, keep.attributes=TRUE), y)) | ||
| } | ||
| x = .as_double_integer64(x, keep.attributes=TRUE) | ||
| } else { | ||
| y = .as_double_integer64(y, keep.attributes=TRUE) | ||
| } | ||
| return(x%*%y) | ||
| } | ||
|
|
||
| dx = dim(x) | ||
| dy = dim(y) | ||
| if (length(dx) > 2L || length(dy) > 2L) | ||
| stop("non-conformable arguments", domain="R") | ||
| if (length(dx) <= 1L && length(dy) <= 1L) { | ||
| dx = c(1L, length(x)) | ||
| if (length(x) == length(y)) { | ||
| dy = c(length(y), 1L) | ||
| } else { | ||
| dy = c(1L, length(y)) | ||
| } | ||
| } | ||
| if (length(dx) <= 1L) | ||
| dx = c(1L, dy[1L]) | ||
| if (length(dy) <= 1L) | ||
| dy = c(dx[2L], 1L) | ||
| if (dx[2L] != dy[1L]) | ||
| stop("non-conformable arguments", domain="R") | ||
| dim(x) = dx | ||
| dim(y) = dy | ||
|
|
||
| if (is.double(x)) { | ||
| ret = .Call(C_matmult_double_integer64, x, structure(as.integer64(y), dim=dy), double(dx[1L]*dy[2L])) | ||
| } else if (is.double(y)) { | ||
| ret = .Call(C_matmult_integer64_double, structure(as.integer64(x), dim=dx), y, double(dx[1L]*dy[2L])) | ||
| } else { | ||
| ret = .Call(C_matmult_integer64_integer64, structure(as.integer64(x), dim=dx), structure(as.integer64(y), dim=dy), double(dx[1L]*dy[2L])) | ||
| } | ||
| dim(ret) = c(dx[1L], dy[2L]) | ||
| oldClass(ret) = "integer64" | ||
| ret | ||
| } | ||
|
|
||
| #' @exportS3Method base::as.matrix integer64 | ||
| as.matrix.integer64 = function(x, ...) { | ||
|
hcirellu marked this conversation as resolved.
|
||
| if (is.matrix(x)) { | ||
| x | ||
| } else { | ||
| array(x, c(length(x), 1L), if (!is.null(names(x))) list(names(x), NULL)) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally I think it's overkill to call We have a few ugly checks in |
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.