tensor/0000755000175100001440000000000011751143067011607 5ustar hornikuserstensor/MD50000644000175100001440000000033711751143067012122 0ustar hornikusers01827a83b8531b71806ffe5f76d73ede *DESCRIPTION 9c9f877cef8024f819ea24f4630ae626 *INDEX 9fdfeb11f7ddba6f3aab9aaa6b1ac5dd *NAMESPACE 55fb65eea33abde21f3de38c0ed54b98 *R/tensor.R 047709d8cd7a78f5dc73d25ca4ae5d26 *man/tensor.Rd tensor/man/0000755000175100001440000000000007421255442012362 5ustar hornikuserstensor/man/tensor.Rd0000644000175100001440000000471507421255442014172 0ustar hornikusers\name{tensor} \alias{tensor} \alias{\%*t\%} \alias{\%t*\%} \alias{\%t*t\%} \title{Tensor product of arrays} \description{The tensor product of two arrays is notionally an outer product of the arrays collapsed in specific extents by summing along the appropriate diagonals. For example, a matrix product is the tensor product along the second extent of the first matrix and the first extent of the second. Thus \code{A \%*\% B} could also be evaluated as \code{tensor(A, B, 2, 1)}, likewise \code{A \%*\% t(B)} could be \code{tensor(A, B, 2, 2)}.} \usage{ tensor(A, B, alongA = integer(0), alongB = integer(0)) } \arguments{ \item{A, B}{Numerical vectors, matrices or arrays} \item{alongA}{Extents in \code{A} to be collapsed} \item{alongB}{Extents in \code{B} to be collapsed} } \details{This code does the `obvious' thing, which is to perm the "along" extents to the end (for \code{A}) and beginning (for \code{B}) of the two objects and then do a matrix multiplication and reshape.} \value{Generally, an array with dimension comprising the remaining extents of \code{A} concatenated with the remaining extents of \code{B}. If both \code{A} and \code{B} are completely collapsed then the result is a scalar \bold{without} a \code{dim} attribute. This is quite deliberate and consistent with the general rule that the dimension of the result is the sum of the original dimensions less the sum of the collapse dimensions (and so could be zero). A 1D array of length 1 arises in a different set of circumstances, eg if \code{A} is a 1 by 5 matrix and \code{B} is a 5-vector then \code{tensor(A, B, 2, 1)} is a 1D array of length 1.} \section{Shortcuts}{Some special cases of \code{tensor} may be independently useful, and these have got shortcuts as follows. \tabular{ll}{ \%*t\% \tab Matrix product \code{A \%*\% t(B)} \cr \%t*\% \tab Matrix product \code{t(A) \%*\% B} \cr \%t*t\% \tab Matrix product \code{t(A) \%*\% t(B)} } } \author{Jonathan Rougier, \email{J.C.Rougier@durham.ac.uk}} \seealso{\code{\link{matmult}}, \code{\link{aperm}}} \examples{ A <- matrix(1:6, 2, 3) dimnames(A) <- list(happy = LETTERS[1:2], sad = NULL) B <- matrix(1:12, 4, 3) stopifnot(A \%*\% t(B) == tensor(A, B, 2, 2)) A <- A \%o\% A C <- tensor(A, B, 2, 2) stopifnot(all(dim(C) == c(2, 2, 3, 4))) D <- tensor(C, B, c(4, 3), c(1, 2)) stopifnot(all(dim(D) == c(2, 2))) E <- matrix(9:12, 2, 2) s <- tensor(D, E, 1:2, 1:2) stopifnot(s == sum(D * E), is.null(dim(s))) } \keyword{array} tensor/INDEX0000644000175100001440000000006207320575011012372 0ustar hornikuserstensor Tensor product of arrays tensor/R/0000755000175100001440000000000007320577016012012 5ustar hornikuserstensor/R/tensor.R0000644000175100001440000000313107320577010013437 0ustar hornikusers"tensor" <- function(A, B, alongA = integer(0), alongB = integer(0)) { A <- as.array(A) dimA <- dim(A) dnA <- dimnames(A) if (nnA <- is.null(dnA)) dnA <- rep(list(NULL), length(dimA)) B <- as.array(B) dimB <- dim(B) dnB <- dimnames(B) if (nnB <- is.null(dnB)) dnB <- rep(list(NULL), length(dimB)) if (length(alongA) != length(alongB)) stop("\"along\" vectors must be same length") # special case of both length zero if (length(alongA) == 0) { R <- as.vector(A) %*% t(as.vector(B)) dim(R) <- c(dimA, dimB) if (!(nnA && nnB)) dimnames(R) <- c(dnA, dnB) return(R) } mtch <- dimA[alongA] == dimB[alongB] if (any(is.na(mtch)) || !all(mtch)) stop("Mismatch in \"along\" dimensions") seqA <- seq(along=dimA) allA <- length(seqA) == length(alongA) permA <- c(seqA[-alongA], alongA) if (!all(seqA == permA)) A <- aperm(A, permA) dim(A) <- c( if (allA) 1 else prod(dimA[-alongA]), prod(dimA[alongA]) ) seqB <- seq(along=dimB) allB <- length(seqB) == length(alongB) permB <- c(alongB, seqB[-alongB]) if (!all(seqB == permB)) B <- aperm(B, permB) dim(B) <- c( prod(dimB[alongB]), if (allB) 1 else prod(dimB[-alongB]) ) R <- A %*% B if (allA && allB) R <- drop(R) else { dim(R) <- c( if (allA) integer(0) else dimA[-alongA], if (allB) integer(0) else dimB[-alongB] ) if (!(nnA && nnB)) dimnames(R) <- c(dnA[-alongA], dnB[-alongB]) } R } "%*t%" <- function(x, y) tensor(x, y, 2, 2) "%t*%" <- function(x, y) tensor(x, y, 1, 1) "%t*t%" <- function(x, y) tensor(x, y, 1, 2) tensor/DESCRIPTION0000644000175100001440000000074411751143067013322 0ustar hornikusersPackage: tensor Version: 1.5 Date: 04.05.12 Title: Tensor product of arrays Author: Jonathan Rougier Maintainer: Jonathan Rougier Description: The tensor product of two arrays is notionally an outer product of the arrays collapsed in specific extents by summing along the appropriate diagonals. License: GPL (>= 2) Packaged: 2012-05-04 11:44:41 UTC; mazjcr Repository: CRAN Date/Publication: 2012-05-05 06:18:31 tensor/NAMESPACE0000644000175100001440000000017111750740451013024 0ustar hornikusers# Default NAMESPACE created by R # Remove the previous line if you edit this file # Export all names exportPattern(".")