tensor                package:tensor                R Documentation

_T_e_n_s_o_r _p_r_o_d_u_c_t _o_f _a_r_r_a_y_s

_D_e_s_c_r_i_p_t_i_o_n:

     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 `A %*% B' could also be
     evaluated as `tensor(A, B, 2, 1)', likewise `A %*% t(B)' could be
     `tensor(A, B, 2, 2)'.

_U_s_a_g_e:

     tensor(A, B, alongA = integer(0), alongB = integer(0))

_A_r_g_u_m_e_n_t_s:

    A, B: Numerical vectors, matrices or arrays

  alongA: Extents in `A' to be collapsed

  alongB: Extents in `B' to be collapsed

_D_e_t_a_i_l_s:

     A straightforward implementation of `tensor' in R would be to perm
     the along extents to the end of each object, reshape each object
     as a matrix with the columns corresponding to the along extents,
     take the matrix product of the first object with the transpose of
     the second, and then reshape the result. This happens to be very
     expensive if the objects are large (and people who want tensors
     often have large objects!).  But it is recommended if speed is an
     issue and RAM is ample.

     This `tensor' implements the tensor product without perming or
     reshaping using the concept of `strides', which will be familiar
     to numerical programmers in Python.  In other words, if `A', `B'
     and their required tensor product fit into the available memory,
     then the calculation will complete (modulo a few small objects
     created en route).  All code is written in "C", for speed.  `NA'
     is fully supported and the original storage type of the objects
     (integer, double or complex) is preserved, where possible.  This
     might be useful for matrix products on integers (which R promotes
     to doubles): see the Section on Shortcuts below.

_V_a_l_u_e:

     Generally, an array with dimension comprising the remaining
     extents of `A' concatenated with the remaining extents of `B'.

     If both `A' and `B' are completely collapsed then the result is a
     scalar without a `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 `A' is a 1 by 5 matrix
     and `B' is a 5-vector then `tensor(A, B, 2, 1)' is a 1D array of
     length 1.

_S_h_o_r_t_c_u_t_s:

     Some special cases of `tensor' may be independently useful, and
     these have got shortcuts as follows.

       %O%    Outer product of `A' and `B'
       %*t%   Matrix product `A %*% t(B)'
       %t*%   Matrix product `t(A) %*% B'
       %t*t%  Matrix product `t(A) %*% t(B)'

_A_u_t_h_o_r(_s):

     Jonathan Rougier, J.C.Rougier@durham.ac.uk

_S_e_e _A_l_s_o:

     `outer'

_E_x_a_m_p_l_e_s:

       A <- matrix(1:6, 2, 3) # has storage mode "integer"
       dimnames(A) <- list(happy = LETTERS[1:2], sad = NULL) # just for fun!
       B <- matrix(1:12, 4, 3)
       all(A %*% t(B) == tensor(A, B, 2, 2)) # TRUE
       A %*t% B # same answer

       A <- A %O% A # now 2 by 3 by 2 by 3
       C <- tensor(A, B, 2, 2) # will be 2 by 2 by 3 by 4
       D <- tensor(C, B, c(4, 3), c(1, 2)) # will be 2 by 2

       E <- matrix(9:12, 2, 2)
       s <- tensor(D, E, 1:2, 1:2) # scalar, NO dim attribute
       s == sum(D * E) # TRUE

