Skip to content

Outer

Status: Stable

documented, exercised by the test suite and/or worked examples, with no known limitations recorded.

Description

Outer[f,list1,list2,...]

gives the generalized outer product of the listi, forming all possible combinations of the lowest-level elements in each of them, and feeding them as arguments to f.

Outer[f,list1,list2,...,n]

treats as separate elements only sublists at level n in the listi.

Outer[f,list1,list2,...,n1,n2,...]

treats as separate elements only sublists at level ni in the corresponding listi.

Examples (8)

Every input below was run against the current Mathilda build and its output recorded.

Basic examples (3)

In[1]:= Outer[f, {a, b}, {x, y, z}]
Out[1]= {{f[a, x], f[a, y], f[a, z]}, {f[b, x], f[b, y], f[b, z]}}

In[2]:= Outer[Times, {1, 2, 3, 4}, {a, b, c}]
Out[2]= {{a, b, c}, {2 a, 2 b, 2 c}, {3 a, 3 b, 3 c}, {4 a, 4 b, 4 c}}

In[3]:= Outer[g, f[a, b], f[x, y, z]]
Out[3]= f[f[g[a, x], g[a, y], g[a, z]], f[g[b, x], g[b, y], g[b, z]]]

Applications (5)

In[4]:= Outer[Times, {1, 2, 3}, {a, b, c}]
Out[4]= {{a, b, c}, {2 a, 2 b, 2 c}, {3 a, 3 b, 3 c}}

In[5]:= Outer[f, {1, 2}, {x, y}]
Out[5]= {{f[1, x], f[1, y]}, {f[2, x], f[2, y]}}

In[6]:= Outer[Times, {1, x, x^2}, {1, x, x^2}]
Out[6]= {{1, x, x^2}, {x, x^2, x^3}, {x^2, x^3, x^4}}

In[7]:= Det[Outer[Times, {a, b, c}, {1, 1, 1}]]
Out[7]= 0

In[8]:= Outer[List, {1, 2}, {a, b}, {X, Y}]
Out[8]= {{{{1, a, X}, {1, a, Y}}, {{1, b, X}, {1, b, Y}}}, {{{2, a, X}, {2, a, Y}}, {{2, b, X}, {2, b, Y}}}}

Implementation notes

Algorithm. builtin_outer computes the generalised outer product Outer[f, t1, t2, ..., {n1, ...}]. It first counts trailing Integer / Infinity arguments as per-tensor depth limits (default INT64_MAX, i.e. descend to the leaves), leaving the remaining arguments after f as the input tensors. The recursive worker outer_rec walks each tensor down to its target depth, collecting one atom per tensor into current_atoms, and at the deepest level emits f[a1, a2, ...]; the assembled tree is then evaluate-d once. The result head for the assembled levels is taken from the first function-typed tensor.

Data structures / limits. Nested Expr* Lists; per-tensor depths in an int64_t[]. With no tensors, f[] is returned evaluated. This is the generic functional-programming Outer, not a linear-algebra-specific kernel; KroneckerProduct and matrix outer products are built on it.

  • Protected.
  • Applying Outer to two tensors of ranks $r$ and $s$ gives a tensor of rank $r+s$.
  • The heads of all listi must be the same, but need not necessarily be List.

Attributes: Protected.

References

See also: List

Notes & additional examples

Notes

Outer[f, l1, l2, ...] forms every combination of lowest-level elements, one from each list, and applies f to it. The result has nesting depth equal to the combined depth of the inputs, so Outer of two vectors is a matrix, of three is a rank-3 array, and so on. With f = Times it is the tensor (outer) product; with a symbolic head it is a complete combination table. The optional level arguments Outer[f, l1, l2, ..., n] (or per-list n1, n2, ...) control which sublists are treated as the separate elements to combine.