Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Directsum #10

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Directsum #10

wants to merge 3 commits into from

Conversation

martincornejo
Copy link

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)

@mcabbott
Copy link
Collaborator

mcabbott commented Jun 5, 2023

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)

@martincornejo
Copy link
Author

martincornejo commented Jun 5, 2023

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants