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.boxdot
TensorCore.boxdot!
TensorCore.hadamard
TensorCore.hadamard!
TensorCore.tensor
TensorCore.tensor!
TensorCore.hadamard
— Functionhadamard(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)
.
TensorCore.hadamard!
— Functionhadamard!(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
.
TensorCore.tensor
— Functiontensor(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)
.
TensorCore.tensor!
— Functiontensor!(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
.
TensorCore.boxdot
— Functionboxdot(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 *
.
TensorCore.boxdot!
— Functionboxdot!(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.