Consider the Matrix
A = [1., 2., 3.; 4., 5., 6]
and the Vector
v = [0.1, 0.2, 0.4]
What is the most efficient "Julianic" way to obtain a new Matrix
whose rows are [cross(A[1, :], v); cross([2, :], v)]
? The result for the numbers above should be [0.2, -0.1, 0.; 0.8, -0.1, 0.3]
How to generalize for N rows in A?
CodePudding user response:
You can do it with dot broadcasting like this:
A = [1 2 3; 4 5 6];
v = [0.1, 0.2, 0.4];
cross.(eachrow(A), Ref(v))
2-element Vector{Vector{Float64}}:
[0.19999999999999996, -0.09999999999999998, 0.0]
[0.7999999999999998, -1.0, 0.30000000000000004]
Note that the original A
in the question is not valid syntax. In Julia, a literal matrix is written with rows having spaces between elements.
CodePudding user response:
You can use BenchmarkTools
to try it out and compare methods.
#Data
A = [1. 2. 3.; 4. 5. 6]
v = [.1, .2, .4]
A2 = [1. 4.; 2. 5.; 3. 6.]
using LinearAlgebra #for command cross
using BenchmarkTools
suite = BenchmarkGroup()
suite["JustLearning"] = @benchmarkable [cross(A[1, :], v), cross(A[2, :], v)]
suite["Dan Getz"] = @benchmarkable vcat([permutedims(cross(r,v)) for r in eachrow(A)]...)
suite["AboAmmar"] = @benchmarkable cross.(eachrow(A), Ref(v))
suite["DNF"] = @benchmarkable hcat([cross(a, v) for a in eachcol(A2)]...)
suite["Add1"] = @benchmarkable [cross(a, v) for a in eachcol(A2)] #As vector
suite["Add2"] = @benchmarkable [cross(a, v) for a in eachcol(A')]
suite["Add3"] = @benchmarkable [cross(a, v) for a in eachrow(A)]
suite["Add4"] = @benchmarkable hcat([cross(a, v) for a in eachrow(A)]...)
tune!(suite);
results = run(suite)
#8-element BenchmarkTools.BenchmarkGroup:
# tags: []
# "Add1" => Trial(328.973 ns)
# "Add4" => Trial(398.335 ns)
# "JustLearning" => Trial(585.604 ns)
# "AboAmmar" => Trial(433.327 ns)
# "Add2" => Trial(330.356 ns)
# "DNF" => Trial(391.129 ns)
# "Dan Getz" => Trial(648.612 ns)
# "Add3" => Trial(323.352 ns)
Depending on how the result should look like the methods differ in time, In case of a matrix DNF is fast in this case. In case you will not change the format of A
hcat([cross(a, v) for a in eachrow(A)]...)
#3×2 Matrix{Float64}:
# 0.2 0.8
# -0.1 -1.0
# 0.0 0.3
hcat([cross(a, v) for a in eachrow(A)]...)'
#2×3 adjoint(::Matrix{Float64}) with eltype Float64:
# 0.2 -0.1 0.0
# 0.8 -1.0 0.3
looks to be performant.