Higher dimensional cross product in LinearAlgebra

Is there any function (specifically in LineaAlgebra or Base Julia) similar to cross, but one that works(gives cross product) on (mathematically speaking) higher dimensional(length) Vectors??? As cross currently only supports 3 dimensional(length) Vectors (see this).

The reason I am asking this is that, this might be a cool(& easy) feature to contribute to as a newcomer(to open source and julia). But, I first want to check if it is possible to open up an issue for this(& work on it). I have already searched through issues in Julia’s github repo but, found none related. Hence, I am asking here to know whether(if yes, then where) this topic was discussed in the past(specifically in julia), so I can determine whether to open up a PR for this(if possible).

The cross product is an intrinsically 3-dimensional idea.

In the SO thread, “What you are looking for is the wedge or exterior product” is the right idea, but maybe not so readable. Instead of a map from two vectors to another vector, the general object is a map from two 1-forms to a 2-form, but in 3 dimensions, this 2-form is hodge dual to another 1-form, and that’s what the cross product gives you. (That’s also why you can think of area elements in 3D as being their normal vectors.) In more, or fewer, dimensions, the 2-form isn’t dual to a 1-form.

There are quite a few Julia packages playing with related ideas, with varying goals & levels of abstraction. In no particular order: https://github.com/Jutho/TensorKit.jl, https://github.com/simeonschaub/CoolTensors.jl, https://github.com/EricForgy/TensorAlgebra.jl, https://github.com/chakravala/Grassmann.jl.

5 Likes

Forgive me for not clearing this up earlier. But yeah, by cross product, I meant like “wedge” or “exterior” product(as suggested) and not an outer vector product. But, I think in general, the idea is similar(for 3 dimension case). I just want to (slightly)extend that idea(if you look at the code) of LinearAlgebra’s cross product to higher dimensional Vectors.

I also looked at the packages you mentioned. But, some of them uses (Vector)outer product in place of cross(wedge/exterior) product, some of them don’t have definition to cross product because of the package infancy, and some of the major packages still uses the same definition in LinearAlgebra library for their own cross products(may be they were thinking that someone might someday extend that definition).

P.S. Apoligies if this sounds dumb.

Here is perhaps an implementation matching what you want? https://github.com/eschnett/DifferentialForms.jl

1 Like

Nope, it’s not that either.

let me explain by example:

  1. we get zero Vector when we cross two vectors that are in the same direction.
    e.x. LinearAlgebra.cross([1,1,1], [2,2,2]) .|> iszero |> all this gives true
    similarly I want to implement in julia(I have the code just to make a pr) something like,
    cross([1,1,1,1], [2,2,2,2], [3,3,3,3]) .|> iszero |> all again true

  2. by crossing(applying cross product to) N-1 orthogonal Vectors(of N dimensions) we get another vector(in same dimensional space) that is also orthogonal to the Vectors used in the cross product.
    e.x. LinearAlgebra.cross([0,1,0], [0,0,1]) == [1,0,0] # true
    similarly,
    cross([0,1,0,0], [0,0,1,0], [0,0,0,1]) == [1, 0, 0, 0] # true

  3. And for any vector,:
    e.x. LinearAlgebra.cross([1,2,3], [3,5,-1]) == [-17, 10, -1] # true
    similarly,
    cross([1,1,0,2,4], [3,0,1,-5,3], [3,3,3,1,2], [-4,2,0,7,1]) == [-13.0, -221.0, 195.0, 51.0, 33.0] # true

julia> A = [1 1 0 2 4
       3 0 1 -5 3
       3 3 3 1 2
       -4 2 0 7 1
       1 1 1 1 1]

julia> det(A)*(A\[0,0,0,0,1])
5-element Array{Float64,1}:
  -12.999999999999991
 -220.99999999999997
  195.0
   51.0
   32.99999999999999

1 Like
julia> using DifferentialForms

julia> v = Form{3,1}((0,1,0)); w =  Form{3,1}((0,0,1));

julia> hodge(wedge(v,w)) # the cross product
Int64⟦[1]:1, [2]:0, [3]:0⟧{3,1}

julia> v = Form{4,1}((0,1,0,0)); w = Form{4,1}((0,0,1,0)); u = Form{4,1}((0,0,0,1));

julia> hodge(wedge(v,w,u)) # notice the orientation 
Int64⟦[1]:-1, [2]:0, [3]:0, [4]:0⟧{4,1}

julia> v = Form{5,1}((1,1,0,2,4)); w = Form{5,1}((3,0,1,-5,3)); u = Form{5,1}((3,3,3,1,2)); x = Form{5,1}((-4,2,0,7,1));

julia> hodge(wedge(v,w,u,x))
Int64⟦[1]:-13, [2]:-221, [3]:195, [4]:51, [5]:33⟧{5,1}
2 Likes

Yup, that’s what i was asking for(& this was exactly what i did in my definition of cross). A simple solution to a simple problem.

Oh yeah, my bad for skimming through docs.

There was a PR previously for the cross product in 7 dimensions, which was declined since it wasn’t clear which definition to choose: https://github.com/JuliaLang/julia/pull/32107. The conclusion there was that the definition was better in a package so that Base Julia isn’t locked into a particular definition forever.

3 Likes

Thnx, that answers this thread :+1:

1 Like

It seems unfortunate that Base exports the cross function and \times symbol for something that is actually pretty rare.

3 Likes

Just a pedantic note, they’re exported by LinearAlgebra, not Base.

3 Likes

I am using version 1.5.1 of julia & Base doesn’t export cross not \times symbol.

Very good point, thanks! I guess this was a memory from >2 years ago.

Tbh, I think there is a decent case for including the wedge product in the base linear algebra package since it is extremely useful in a wide range of situations, and exporting it from LinearAlgebra would mean wider ecosystem support for it just like with the tensor/kronecker product.

The 7-dimensional cross product on the other hand is a fairly weird constuction that involves fixing a particular trivector (3-form), so unlike in the 3d case where there is only one trivector up to scalar multiplication (with sign giving chirality), the 7-dimensional cross product does not transform in the same way as its factors under rotations for example. It is only does that for a G_2 factor of SO(7) (though it behaves more nicely for 7d vectors over finite fields). As opposed to the wedge product which is completely unique and depends on nothing, just like the tensor product.

Would ∧(::Vector, ::Vector) return a Matrix?

The loudest objection to putting ⊗ into LinearAlgebra was that it was also going to return a matrix for something which really has two of the same indices, while most other parts of the package assume a Matrix has one upstairs & one downstairs. So we got TensorCore.jl, but ideally this will be folded back in at some point.

1 Like

I would say yes since both argument types are Vectors. ∧(::Form{N}, ::Form{M}) would return Form{N+M} for a hypothetical Form ( or Covector ) type.
Like ⊗ I think wedge would be a good one to include in base if/when covariance is taken seriously.

Right, the issue here regarding index types is the lack of distinction between vectors and dual vectors. The tensor product of a vector with a dual vector is basically a matrix, just like the wedge product. Julia doesn’t quite distinguish between vectors and their duals though.

Julia does indeed distinguish between vectors and dual vectors though adjoint. It’s just that it doesn’t generalize well to higher rank objects.

Something with two contravriant or two covariant or one covariant and one contra variant index are all Matrixes.

1 Like