blob: 4676ad7539f55cca7161664965fb9c307977693c [file] [log] [blame]
# File src/library/base/R/outer.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1995-2018 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 2 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/
outer <- function (X, Y, FUN = "*", ...)
{
if(is.array(X)) {
dX <- dim(X)
nx <- dimnames(X)
no.nx <- is.null(nx)
} else { # a vector
dX <- length(X) # cannot be long, as form a matrix below
no.nx <- is.null(names(X))
if(!no.nx) nx <- list(names(X))
}
if(is.array(Y)) {
dY <- dim(Y)
ny <- dimnames(Y)
no.ny <- is.null(ny)
} else { # a vector
dY <- length(Y)
no.ny <- is.null(names(Y))
if(!no.ny) ny <- list(names(Y))
}
robj <-
if (is.character(FUN) && FUN=="*") {
if(!missing(...)) stop('using ... with FUN = "*" is an error')
## this is for numeric vectors, so dropping attributes is OK
tcrossprod(as.vector(X), as.vector(Y))# faster than as.vector(X) %*% t(as.vector(Y))
} else {
FUN <- match.fun(FUN)
## Y may have a class, so don't use rep.int
Y <- rep(Y, rep.int(length(X), length(Y)))
## length.out is not an argument of the generic rep()
## X <- rep(X, length.out = length(Y))
if(length(X))
X <- rep(X, times = ceiling(length(Y)/length(X)))
FUN(X, Y, ...)
}
dim(robj) <- c(dX, dY) # careful not to lose class here
## no dimnames if both don't have ..
if(!(no.nx && no.ny)) {
if(no.nx) nx <- vector("list", length(dX)) else
if(no.ny) ny <- vector("list", length(dY))
dimnames(robj) <- c(nx, ny)
}
robj
}
## Binary operator, hence don't simply do "%o%" <- outer.
`%o%` <- function(X, Y) outer(X, Y)