TensorCore.jl

This package is intended as a lightweight foundation for tensor operations across the Julia ecosystem. Currently it exports three operations, hadamard, tensor and boxdot, and corresponding unicode operators , and .

API

TensorCore.hadamardFunction
hadamard(a, b)
a ⊙ b

For arrays a and b, perform elementwise multiplication. a and b must have identical axes.

can be passed as an operator to higher-order functions.

Examples

julia> a = [2, 3]; b = [5, 7];

julia> a ⊙ b
2-element Vector{Int64}:
 10
 21

julia> a ⊙ [5]
ERROR: DimensionMismatch: Axes of `A` and `B` must match, got (Base.OneTo(2),) and (Base.OneTo(1),)
[...]

See also hadamard!(y, a, b).

source
TensorCore.hadamard!Function
hadamard!(dest, A, B)

Similar to hadamard(A, B) (which can also be written A ⊙ B), but stores its results in the pre-allocated array dest.

source
TensorCore.tensorFunction
tensor(A, B)
A ⊗ B

Compute the tensor product of A and B. If C = A ⊗ B, then C[i1, ..., im, j1, ..., jn] = A[i1, ... im] * B[j1, ..., jn].

For vectors v and w, the Kronecker product is related to the tensor product by kron(v,w) == vec(w ⊗ v) or w ⊗ v == reshape(kron(v,w), (length(w), length(v))).

Examples

julia> a = [2, 3]; b = [5, 7, 11];

julia> a ⊗ b
2×3 Matrix{Int64}:
 10  14  22
 15  21  33

See also tensor!(Y,A,B).

source
TensorCore.tensor!Function
tensor!(dest, A, B)

Similar to tensor(A, B) (which can also be written A ⊗ B), but stores its results in the pre-allocated array dest.

source
TensorCore.boxdotFunction
boxdot(A,B) = A ⊡ B    # \boxdot

Generalised matrix multiplication: Contracts the last dimension of A with the first dimension of B, for any ndims(A) & ndims(B). If both are vectors, then it returns a scalar == sum(A .* B).

Examples

julia> A = rand(3,4,5); B = rand(5,6,7);

julia> size(A ⊡ B)
(3, 4, 6, 7)

julia> typeof(rand(5) ⊡ rand(5))
Float64

julia> try B ⊡ A catch err println(err) end
DimensionMismatch("neighbouring axes of `A` and `B` must match, got Base.OneTo(7) and Base.OneTo(3)")

This is the same behaviour as Mathematica's function Dot[A, B]. It is not identicaly to Python's numpy.dot(A, B), which contracts with the second-last dimension of B instead of the first, but both keep all the other dimensions. Unlike Julia's LinearAlgebra.dot, it does not conjugate A, so these two agree only for real-valued vectors.

When interacting with Adjoint vectors, this always obeys (x ⊡ y)' == y' ⊡ x', and hence may sometimes return another Adjoint vector. (And similarly for Transpose.)

julia> M = rand(5,5); v = rand(5);

julia> typeof(v ⊡ M')
Vector{Float64} (alias for Array{Float64, 1})

julia> typeof(M ⊡ v')  # adjoint of the previous line
LinearAlgebra.Adjoint{Float64, Vector{Float64}}

julia> typeof(v' ⊡ M')  # same as *, and equal to adjoint(M ⊡ v)
LinearAlgebra.Adjoint{Float64, Vector{Float64}}

julia> typeof(v' ⊡ v)
Float64

See also boxdot!(Y,A,B), which is to as mul! is to *.

source
TensorCore.boxdot!Function
boxdot!(Y, A, B, α=1, β=0)

In-place version of boxdot, i.e. Y .= (A ⊡ B) .* β .+ Y .* α. Like 5-argument mul!, the use of α, β here requires Julia 1.3 or later.

source