Home > Enterprise >  Cross Product in Julia
Cross Product in Julia

Time:09-12

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.

  • Related