Reputation: 4352
Let
A = rand(3,3);B = rand(3,3)
I can multiply first column of A : A[:,1]
with third row of matrix B : B[3,:]
by the command:
reshape(A[:,1],3,1)*reshape(B[3,:],1,3)
to make a 3x3 matrix.
The direct computation
A[:,1]*B[3,:]
is giving the error:
ERROR: MethodError: no method matching *(::Vector{Float64}, ::Vector{Float64})
Closest candidates are:
*(::Any, ::Any, ::Any, ::Any...) at operators.jl:560
*(::StridedMatrix{T}, ::StridedVector{S}) where {T<:Union{Float32, Float64, ComplexF32, ComplexF64}, S<:Real} at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\LinearAlgebra\src\matmul.jl:44
*(::StridedVecOrMat{T} where T, ::LinearAlgebra.Adjoint{var"#s832", var"#s831"} where {var"#s832", var"#s831"<:LinearAlgebra.LQPackedQ}) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\LinearAlgebra\src\lq.jl:254
...
Stacktrace:
[1] top-level scope
@ REPL[2]:1
Is there any other short/clear method to do this operation?
Answer : A[:, 1:1] * B[3:3, :]
and A[:, 1] * B[3, :]'
from @phipsgabler's reply. Or view(A, :, 1)*view(B, 3, :)'
, @views A[:, 1] * B[3, :]'
without copying rows or columns.
Upvotes: 1
Views: 374
Reputation: 20980
A[:, 1]
and B[3, :]
are both Vector
s -- rank 1 -- so it is not automatically clear what you want here. The more likely option would be the inner product:
julia> dot(A[:, 1], B[3, :])
0.8875027511646011
julia> A[:, 1]' * B[3, :]
0.8875027511646011
But it seems you want the outer product:
julia> reshape(A[:,1],3,1)*reshape(B[3,:],1,3)
3×3 Matrix{Float64}:
0.689437 0.246968 0.190616
0.400674 0.143528 0.110778
0.197257 0.0706608 0.0545377
julia> A[:, 1:1] * B[3:3, :]
3×3 Matrix{Float64}:
0.689437 0.246968 0.190616
0.400674 0.143528 0.110778
0.197257 0.0706608 0.0545377
julia> A[:, 1] * B[3, :]'
3×3 Matrix{Float64}:
0.689437 0.246968 0.190616
0.400674 0.143528 0.110778
0.197257 0.0706608 0.0545377
To explain: by using a range, 1:1
, instead of an index, the result will still be a matrix (just like your reshape
approach):
julia> B[3:3, :]
1×3 Matrix{Float64}:
0.938292 0.336112 0.259419
That way the *
is well defined as the matrix product between a one-column matrix and a one-row matrix.
The same holds if you transpose one of the vectors:
julia> B[3, :]'
1×3 adjoint(::Vector{Float64}) with eltype Float64:
0.938292 0.336112 0.259419
The product between a vector and a covector is also well-defined.
The last option is to use kron
; this however vectorizes the result, and you have to reshape the output:
julia> reshape(kron(A[:, 1], B[3, :]), 3, 3)
3×3 Matrix{Float64}:
0.689437 0.400674 0.197257
0.246968 0.143528 0.0706608
0.190616 0.110778 0.0545377
Upvotes: 4