blob: 464cf3ee09981668080b44a05c1f79fb1d745406 [file] [log] [blame]
# File src/library/methods/R/makeBasicFunsList.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1995-2017 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available at
# https://www.R-project.org/Licenses/
## the executable code to complete the generics corresponding to primitives,
## and to define the group generics for these functions.
## uses the primitive list and the function .addBasicGeneric
## defined (earlier) in BasicFunsList.R
utils::globalVariables(".addBasicGeneric")
.makeBasicFuns <- function(where)
{
funs <- get(".BasicFunsList", envir=where)
## First, set up the existing functions in the list as valid generics.
## This will override anything except the S4 group generics.
curNames <- names(funs)
for(i in seq_along(funs)) {
val <- funs[[i]]
if (is.function(val))
funs <- .addBasicGeneric(funs, curNames[[i]], val, "")
}
## Next, add the remaining primitive generics
prims <- names(.GenericArgsEnv)
new_prims <- setdiff(prims, names(funs))
for(nm in new_prims) {
f <- .GenericArgsEnv[[nm]]
body(f) <- substitute(standardGeneric(ff), list(ff=val))
funs <- .addBasicGeneric(funs, nm, f, "")
}
## Then add all the primitives that are not already there.
ff <- as.list(baseenv(), all.names=TRUE)
prims <- ff[vapply(ff, is.primitive, logical(1L))]
new_prims <- setdiff(names(prims), names(funs))
add <- rep(list(FALSE), length(new_prims))
names(add) <- new_prims
funs <- c(funs, add)
## the Math group.
members <- c("abs", "sign", "sqrt",
"ceiling", "floor", "trunc",
"cummax", "cummin", "cumprod", "cumsum",
"exp", "expm1",
"log", "log10", "log2", "log1p",
"cos", "cosh", "sin", "sinh", "tan", "tanh",
"acos", "acosh", "asin", "asinh", "atan", "atanh",
"cospi", "sinpi", "tanpi",
"gamma", "lgamma", "digamma", "trigamma"
)
for(f in members) {
funs <-
.addBasicGeneric(funs, f,
if(f %in% c("log", "trunc")) {
function(x, ...) standardGeneric("")
} else function(x) standardGeneric(""),
"Math")
}
setGroupGeneric(where=where, "Math", function(x)NULL,
knownMembers = members, package = "base")
## The Math2 group.
funs <- .addBasicGeneric(funs, "round",
function(x, digits = 0) standardGeneric(""),
"Math2")
funs <- .addBasicGeneric(funs, "signif",
function(x, digits = 6) standardGeneric(""),
"Math2")
setGroupGeneric(where = where, "Math2", function(x, digits) NULL,
knownMembers = c("round", "signif"), package = "methods")
## The Arith group
members <- c("+", "-", "*", "^", "%%", "%/%", "/")
for(f in members)
funs <- .addBasicGeneric(funs, f, function(e1, e2) standardGeneric(""),
"Arith")
setGroupGeneric(where = where, "Arith", function(e1, e2)NULL,
group = "Ops", knownMembers = members, package = "base")
## the Compare group
members <- c("==", ">", "<", "!=", "<=", ">=")
for(f in members)
funs <- .addBasicGeneric(funs, f, function(e1, e2) standardGeneric(""),
"Compare")
setGroupGeneric(where = where, "Compare", function(e1, e2)NULL,
group = "Ops", knownMembers = members, package = "methods")
## The Logic group
members <- c("&", "|") ## *not* "!" since that has only one argument
for(f in members)
funs <- .addBasicGeneric(funs, f, function(e1, e2) standardGeneric(""),
"Logic")
setGroupGeneric(where = where, "Logic", function(e1, e2) NULL,
group = "Ops", knownMembers = members, package = "base")
## the Ops group generic
setGroupGeneric(where = where,"Ops", function(e1, e2) NULL,
knownMembers = c("Arith", "Compare", "Logic"),
package = "base")
## The Summary group
## These are a bit problematic, since they essentially have "..."
## as their only data-related formal argument. The treatment
## since S3 has been to define the generic with a special first
## argument, to allow method dispatch. But the method had better
## invoke the generic recursively or perform some other special
## computations, in order to avoid unintended anomalies, such as
## !identical(max(x,y), max(y,x))
members <- c("max", "min", "range", "prod", "sum", "any", "all")
for(f in members)
funs <- .addBasicGeneric(funs, f, function (x, ..., na.rm = FALSE)
standardGeneric(""),
"Summary")
setGroupGeneric(where = where, "Summary",
function(x, ..., na.rm = FALSE) NULL,
knownMembers = members, package = "base")
## The Complex group
## R adds this group to the previous S language function groups,
## for all the operations defined on complex numbers. For
## applications wanting to define a new class that extends the
## concept of complex numbers, a function group is likely to be
## useful since all these functions may operate in a similar
## manner (by analogy, e.g., with the Math group).
members <- c("Arg", "Conj", "Im", "Mod", "Re")
for(f in members)
funs <- .addBasicGeneric(funs, f, function(z) standardGeneric(""),
"Complex")
setGroupGeneric(where=where,"Complex", function(z)NULL,
knownMembers = members, package = "base")
funs <- .addBasicGeneric(funs, "unlist", internal=TRUE)
### TODO: bring back if/when .Internal(is.unsorted()) is useful to override
## funs <- .addBasicGeneric(funs, "is.unsorted", internal=TRUE,
## internalArgs=c("x", "strictly"))
funs <- .addBasicGeneric(funs, "as.vector", internal=TRUE)
funs <- .addBasicGeneric(funs, "lengths", internal=TRUE)
## funs <- .addBasicGeneric(funs, "nchar", internal=TRUE)
## funs <- .addBasicGeneric(funs, "rep_len", internal=TRUE)
## funs <- .addBasicGeneric(funs, "rep.int", internal=TRUE)
assign(".BasicFunsList", funs, envir=where)
rm(.addBasicGeneric, envir=where)
}
.initImplicitGenerics <- function(where)
{
## create implicit generics & possibly methods for the functions in .BasicFunsList.
setGeneric("with", signature = "data", where = where)
setGenericImplicit("with", where, FALSE)
## when setMethod()ing on chol2inv, one should *not* have to deal with
## arguments 'size' and 'LINPACK' :
setGeneric("chol2inv", function(x, ...) standardGeneric("chol2inv"),
useAsDefault = function(x, ...) base::chol2inv(x, ...),
signature = "x", where = where)
setGenericImplicit("chol2inv", where, FALSE)
setGeneric ("determinant", function(x, logarithm=TRUE, ...) standardGeneric("determinant"),
useAsDefault = function(x, logarithm=TRUE, ...)
base::determinant(x, logarithm, ...),
signature = c("x", "logarithm"), where = where)
setGenericImplicit("determinant", where, FALSE)
setGeneric("rcond", function(x, norm, ...) standardGeneric("rcond"),
useAsDefault = function(x, norm, ...) base::rcond(x, norm, ...),
signature = c("x", "norm"), where = where)
setGenericImplicit("rcond", where, FALSE)
setGeneric("norm", function(x, type, ...) standardGeneric("norm"),
useAsDefault = function(x, type, ...) base::norm(x, type, ...),
signature = c("x", "type"), where = where)
## this method *belong*s to the generic:
setMethod("norm", signature(x = "ANY", type = "missing"),
function (x, type, ...) norm(x, type = "O", ...))
setGenericImplicit("norm", where, FALSE)
setGeneric("backsolve", function(r, x, k = ncol(r), upper.tri = TRUE, transpose = FALSE, ...)
standardGeneric("backsolve"),
useAsDefault =
function(r, x, k = ncol(r), upper.tri = TRUE, transpose = FALSE, ...)
base::backsolve(r, x, k = k,
upper.tri = upper.tri, transpose = transpose, ...),
signature = c("r", "x"), where = where)
setGenericImplicit("backsolve", where, FALSE)
setGeneric("colMeans", function(x, na.rm = FALSE, dims = 1, ...)
standardGeneric("colMeans"),
useAsDefault = function(x, na.rm = FALSE, dims = 1, ...)
base::colMeans(x, na.rm=na.rm, dims=dims, ...),
signature = "x", where = where)
setGeneric("colSums", function(x, na.rm = FALSE, dims = 1, ...)
standardGeneric("colSums"),
useAsDefault = function(x, na.rm = FALSE, dims = 1, ...)
base::colSums(x, na.rm=na.rm, dims=dims, ...),
signature = "x", where = where)
setGeneric("rowMeans", function(x, na.rm = FALSE, dims = 1, ...)
standardGeneric("rowMeans"),
useAsDefault = function(x, na.rm = FALSE, dims = 1, ...)
base::rowMeans(x, na.rm=na.rm, dims=dims, ...),
signature = "x", where = where)
setGeneric("rowSums", function(x, na.rm = FALSE, dims = 1, ...)
standardGeneric("rowSums"),
useAsDefault = function(x, na.rm = FALSE, dims = 1, ...)
base::rowSums(x, na.rm=na.rm, dims=dims, ...),
signature = "x", where = where)
setGenericImplicit("colMeans", where, FALSE)
setGenericImplicit("colSums", where, FALSE)
setGenericImplicit("rowMeans", where, FALSE)
setGenericImplicit("rowSums", where, FALSE)
setGeneric("crossprod", function(x, y = NULL, ...) standardGeneric("crossprod"),
useAsDefault = function(x, y = NULL, ...) base::crossprod(x, y),
signature = c("x", "y"), where = where)
setGeneric("tcrossprod", function(x, y = NULL, ...) standardGeneric("tcrossprod"),
useAsDefault = function(x, y = NULL, ...) base::tcrossprod(x, y),
signature = c("x", "y"), where = where)
setGenericImplicit("crossprod", where, FALSE)
setGenericImplicit("tcrossprod", where, FALSE)
setGeneric("sample", function(x, size, replace = FALSE, prob = NULL, ...)
standardGeneric("sample"),
useAsDefault = function(x, size, replace = FALSE, prob = NULL, ...)
base::sample(x, size, replace=replace, prob=prob, ...),
signature = c("x", "size"), where = where)
setGenericImplicit("sample", where, FALSE)
## qr.R(): signature should only have "qr", args should have "..."
setGeneric("qr.R", function(qr, complete = FALSE, ...) standardGeneric("qr.R"),
useAsDefault= function(qr, complete = FALSE, ...)
base::qr.R(qr, complete=complete),
signature = "qr", where = where)
setGenericImplicit("qr.R", where, FALSE)
## our toeplitz() only has 'x'; want the generic "here" rather than "out there"
setGeneric("toeplitz", function(x, ...) standardGeneric("toeplitz"),
useAsDefault= function(x, ...) stats::toeplitz(x),
signature = "x", where = where)
setGenericImplicit("toeplitz", where, FALSE)
## svd(): signature should only have "x" (no 'nu', 'nv' ..)
setGeneric("svd", function(x, ...) standardGeneric("svd"),
useAsDefault= function(x, ...) base::svd(x, ...),
signature = "x", where = where)
setGenericImplicit("svd", where, FALSE)
## not implicitGeneric() which is not yet available "here"
registerImplicitGenerics(where = where)
}