| # 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) |