TensorCore.jl icon indicating copy to clipboard operation
TensorCore.jl copied to clipboard

Directsum

Open martincornejo opened this issue 1 year ago • 2 comments

Implements directsum (https://en.wikipedia.org/wiki/Matrix_addition#Direct_sum) and unicode operator . Currently it is limited to matrices but it could be extended to support multiple dimentsions (similar to the current behavior between Vector ⊕ Matrix)

martincornejo avatar Jun 05 '23 13:06 martincornejo

For vectors, the direct sum is vcat(x, y) instead of cat(A, B; dims=(1,2)) for matrices. Is there a clear generalisation to all dimensions?

The present function seems to treat any mix of vectors & matrices as if they were matrices:

julia> A = [1 2 3; 4 5 6]; B = [7 8 9; 0 10 20];

julia> directsum([1,2,3], [77, 88, 99])
6×2 Matrix{Int64}:
 1   0
 2   0
 3   0
 0  77
 0  88
 0  99

julia> directsum(A, [77, 88, 99])
5×4 Matrix{Int64}:
 1  2  3   0
 4  5  6   0
 0  0  0  77
 0  0  0  88
 0  0  0  99

julia> @btime directsum($A, $B);  # this PR
  min 1.246 μs, mean 1.329 μs (11 allocations, 640 bytes)

julia> @btime cat($A, $B; dims=Val((1,2)));
  min 477.990 ns, mean 505.022 ns (15 allocations, 672 bytes)

mcabbott avatar Jun 05 '23 14:06 mcabbott

For vectors, the direct sum is vcat(x, y) instead of cat(A, B; dims=(1,2))

Ah, you're right!

The present function seems to treat any mix of vectors & matrices as if they were matrices

Should mixing matrix and vector be undefined? And should in that case the user explicitly then provide a 1-column matrix instead?

julia> @btime cat($A, $B; dims=Val((1,2)));

Ah, that is a neat trick I just learned! cat over multiple dimensions 😊

Is there a clear generalisation to all dimensions?

To be honest, I'm not sure. But I remember reading somewhere (hopefully not taking it out of context), that it should follow $\dim A \oplus B = \dim A + \dim B$

In that sense, it can be generalized.

julia> AA = [A;;;A]; B = [B;;;B];

julia> size(cat(AA, BB, dims=(1,2,3))) == size(AA) .+ size(BB)
true

julia> size(cat(AA, BB, dims=(2,3))) == size(AA) .+ size(BB)
false

Maybe something like this

function directsum2(A::AbstractArray{T,N}, B::AbstractArray{S,M}) where {T,N,S,M}
    maxdim = max(N, M)
    return cat(A, B, dims=1:maxdim)
end

julia> directsum2(rand(2), rand(2))
4-element Vector{Float64}:
 0.7422427057509033
 0.8062369093673359
 0.484623525272175
 0.856149610025547

julia> directsum2(rand(2,2), rand(2,2))
4×4 Matrix{Float64}:
 0.247132  0.586941  0.0       0.0
 0.113415  0.250725  0.0       0.0
 0.0       0.0       0.369446  0.13091
 0.0       0.0       0.933767  0.595314

julia> @btime directsum2($A, $B);
  1.570 μs (28 allocations: 1.00 KiB)

But it seems there is a time penalty for generalizing)

martincornejo avatar Jun 05 '23 17:06 martincornejo