# Find the Cross Product

The cross product of two three-dimensional vectors $$\\vec a\$$ and $$\\vec b\$$ is the unique vector $$\\vec c\$$ such that:

• ﻿$$\\vec c\$$ is orthogonal to both $$\\vec a\$$ and $$\\vec b\$$

• The magnitude of $$\\vec c\$$ is equal to the area of the parallelogram formed by $$\\vec a\$$ and $$\\vec b\$$

• The directions of $$\\vec a\$$, $$\\vec b\$$, and $$\\vec c\$$, in that order, follow the right-hand rule.

There are a few equivalent formulas for cross product, but one is as follows:

$$\vec a\times\vec b=\det\begin{bmatrix}\vec i&\vec j&\vec k\\a_1&a_2&a_3\\b_1&b_2&b_3\end{bmatrix}$$

where $$\\vec i\$$, $$\\vec j\$$, and $$\\vec k\$$ are the unit vectors in the first, second, and third dimensions.

### Challenge

Given two 3D vectors, write a full program or function to find their cross product. Builtins that specifically calculate the cross product are disallowed.

### Input

Two arrays of three real numbers each. If your language doesn't have arrays, the numbers still must be grouped into threes. Both vectors will have magnitude $$\<2^{16}\$$. Note that the cross product is noncommutative ($$\\vec a\times\vec b=-\bigl(\vec b\times\vec a\bigr)\$$), so you should have a way to specify order.

### Output

Their cross product, in a reasonable format, with each component accurate to four significant figures or $$\10^{-4}\$$, whichever is looser. Scientific notation is optional.

### Test cases

[3, 1, 4], [1, 5, 9]
[-11, -23, 14]

[5, 0, -3], [-3, -2, -8]
[-6, 49, -10]

[0.95972, 0.25833, 0.22140],[0.93507, -0.80917, -0.99177]
[-0.077054, 1.158846, -1.018133]

[1024.28, -2316.39, 2567.14], [-2290.77, 1941.87, 712.09]
[-6.6345e+06, -6.6101e+06, -3.3173e+06]


This is , so the shortest solution in bytes wins.

Maltysen posted a similar challenge, but the response was poor and the question wasn't edited.

• Can the input be taken as a 2D array? Commented Jan 30, 2016 at 3:03
• Yes, as long as 2 is the outer dimension. Commented Jan 30, 2016 at 3:04

# Jelly, 1413 12 bytes

;"s€2U×¥/ḅ-U


Try it online!

### How it works

;"s€2U×¥/ḅ-U Main link. Input: [a1, a2, a3], [b1, b2, b3]

;"           Concatenate each [x1, x2, x3] with itself.
Yields [a1, a2, a3, a1, a2, a3], [b1, b2, b3, b1, b2, b3].
s€2        Split each array into pairs.
Yields [[a1, a2], [a3, a1], [a2, a3]], [[b1, b2], [b3, b1], [b2, b3]].
U         Reverse the order of all arrays in the left argument.
×        Multiply both arguments, element by element.
/    Reduce the 2D array of pairs by this chain.
Reversing yields [a2, a1], [a1, a3], [a3, a2].
Reducing yields [a2b1, a1b2], [a1b3, a3b1], [a3b2, a2b3].
ḅ-  Convert each pair from base -1 to integer.
This yields [a1b2 - a2b1, a3b1 - a1b3, a2b3 - a3b2]
U Reverse the array.
This yields [a2b3 - a3b2, a3b1 - a1b3, a1b2 - a2b1] (cross product).


## Non-competing version (10 bytes)

OK, this is embarrassing, but the array manipulation language Jelly did not have a built-in for array rotation until just now. With this new built-in, we can save two additional bytes.

ṙ-×
ç_ç@ṙ-


This uses the approach from @AlexA.'s J answer. Try it online!

### How it works

ṙ-×     Helper link. Left input: x = [x1, x2, x3]. Right input: y = [y1, y2, y3].

ṙ-      Rotate x 1 unit to the right (actually, -1 units to the left).
This yields [x3, x1, x2].
×     Multiply the result with y.
This yields [x3y1, x1y2, x2y3].

ç_ç@ṙ-  Main link. Left input: a = [a1, a2, a3]. Right input: b = [b1, b2, b3].

ç       Call the helper link with arguments a and b.
This yields [a3b1, a1b2, a2b3].
ç@    Call the helper link with arguments b and a.
This yields [b3a1, b1a2, b2a3].
_       Subtract the result to the right from the result to the left.
This yields [a3b1 - a1b3, a1b2 - a2b1, a2b3 - a3b2].
ṙ-  Rotate the result 1 unit to the right.
This yields [a2b3 - a3b2, a3b1 - a1b3, a1b2 - a2b1] (cross product).

• Convert each pair from base -1? That's just evil. +1 Commented Jan 31, 2016 at 3:43

## LISP, 128 122 bytes

Hi! This is my code:

(defmacro D(x y)(list(*(cadr,x)(caddr,y))(*(caddr,x)(car,y))(*(car,x)(cadr,y))))(defun c(a b)(mapcar #'- (D a b)(D b a)))


I know that it isn't the shortest solution, but nobody has provided one in Lisp, until now :)

Copy and paste the following code here to try it!

(defmacro D(x y)(list(*(cadr,x)(caddr,y))(*(caddr,x)(car,y))(*(car,x)(cadr,y))))(defun c(a b)(mapcar #'- (D a b)(D b a)))

(format T "Inputs: (3 1 4), (1 5 9)~%")
(format T "Result ~S~%~%" (c '(3 1 4) '(1 5 9)))

(format T "Inputs: (5 0 -3), (-3 -2 -8)~%")
(format T "Result ~S~%~%" (c '(5 0 -3) '(-3 -2 -8)))

(format T "Inputs: (0.95972 0.25833 0.22140), (0.93507 -0.80917 -0.99177)~%")
(format T "Result ~S~%" (c '(0.95972 0.25833 0.22140) '(0.93507 -0.80917 -0.99177)))

(format T "Inputs: (1024.28 -2316.39 2567.14), (-2290.77 1941.87 712.09)~%")
(format T "Result ~S~%" (c '(1024.28 -2316.39 2567.14) '(-2290.77 1941.87 712.09)))

• Welcome to Programming Puzzles and Code Golf Stack Exchange. This is a great answer, +1. Well done for answering in a language that isn't going to win, but still golfing it down loads. Often code-golf challenges are more about within languages than between them! Commented Jan 30, 2016 at 13:29

# J, 27 14 bytes

2|.v~-v=.*2&|.


This is a dyadic verb that accepts arrays on the left and right and returns their cross product.

Explanation:

         *2&|.     NB. Dyadic verb: Left input * twice-rotated right input
v=.          NB. Locally assign to v
v~-             NB. Commute arguments, negate left
2|.                NB. Left rotate twice


Example:

    f =: 2|.v~-v=.*2&|.
3 1 4 f 1 5 9
_11 _23 14


Try it here

Saved 13 bytes thanks to randomra!

• @randomra That's awesome, thanks! I'm no J expert so I'm still figuring out how exactly it works but I have a general idea. Commented Jan 30, 2016 at 19:03
• Some clarifications: *2&|. is a fork of two verbs: * and 2&|.. It multiplies the left input by a rotated by 2 right input. This fork is stored in v so when we write v~, it is equivalent to (*2&|.)~, where the ~ swaps the left and right input parameters for the parenthesized part. Commented Jan 30, 2016 at 19:53
• @randomra Okay, that makes sense. Thanks again! Commented Jan 31, 2016 at 3:38

# Dyalog APL, 12 bytes

2⌽p⍨-p←⊣×2⌽⊢


Based on @AlexA.'s J answer and (coincidentally) equivalent to @randomra's improvement in that answer's comment section.

Try it online on TryAPL.

### How it works

2⌽p⍨-p←⊣×2⌽⊢  Dyadic function.
Left argument: a = [a1, a2, a3]. Right argument: b = [b1, b2, b3].

2⌽⊢  Rotate b 2 units to the left. Yields [b3, b1, b2].
⊣×     Multiply the result by a. Yields [a1b3, a2b1, a3b2].
p←       Save the tacit function to the right (NOT the result) in p.
p⍨          Apply p to b and a (reversed). Yields [b1a3, b2a1, b3a2].
-         Subtract the right result (p) from the left one (p⍨).
This yields [a3b1 - a1b3, a1b2 - a2b1, a2b3 - a3b2].
2⌽            Rotate the result 2 units to the left.
This yields [a2b3 - a3b2, a3b1 - a1b3, a1b2 - a2b1].


# C, 156154150148 144 bytes

#include <stdio.h>
main(){float v[6];int i=7,j,k;for(;--i;)scanf("%f",v+6-i);for(i=1;i<4;)j=i%3,k=++i%3,printf("%f ",v[j]*v[k+3]-v[k]*v[j+3]);}


Not going to be winning any prizes for length, but thought I'd have a go anyway.

• Input is a newline- or space-delimited list of components (i.e. a1 a2 a3 b1 b2 b3), output is space-delimited (i.e. c1 c2 c3).
• Cyclically permutes the indices of the two input vectors to calculate the product - takes fewer characters than writing out the determinants!

Demo

Ungolfed:

#include <cstdio>
int main()
{
float v[6];
int i = 7, j, k;
for (; --i; ) scanf("%f", v + 6 - 1);
for (i = 1; i < 4; )
j = i % 3,
k = ++i % 3,
printf("%f ", v[j] * v[k + 3] - v[k] * v[j + 3]);
}

• Welcome to Programming Puzzles and Code Golf Stack Exchange. This is a great answer; well done for answering in a language that won't beat the golfing languages. +1. Commented Jan 30, 2016 at 10:39
• Your first for doesn't need {} Commented Jan 30, 2016 at 11:58
• cheers, updated. Commented Jan 30, 2016 at 15:50
• You can replace &v[6-i] with v+6-i. Also, you can replace semicolon after j=i%3 and k=(i+1)%3 with commas, which makes everything after the for a single statement so you can omit the {}. Finally, if you initialise i to 1 for the second for loop, you can move the increment into k=++i%3 saving a couple of brackets. If you're not worried about warnings and use the right version of C, you can skip the include as well. Commented Feb 1, 2016 at 16:07
• awesome, cheers! My compiler won't accept the omission of the header, so I've stuck with a version I'm able to build. Commented Feb 1, 2016 at 21:20

x(a,b,c)(d,e,f)=(b*f-c*e,c*d-a*f,a*e-b*d)


A straightforward solution.

# Bash + coreutils, 51

eval set {$1}*{$2}
bc<<<"scale=4;$6-$8;$7-$3;$2-$4"

• Line 1 constructs a brace expansion that gives the cartesian product of the two vectors and sets them into the positional parameters.
• Line 2 subtracts the appropriate terms; bc does the arithmetic evaluation to the required precision.

Input is as two comma-separated lists on the command-line. Output as newline-separated lines:

$./crossprod.sh 0.95972,0.25833,0.22140 0.93507,-0.80917,-0.99177 -.07705 1.15884 -1.01812$


# MATL, 17 bytes

!*[6,7,2;8,3,4])d


First input is a, second is b.

Try it online!

### Explanation

!              % input b as a row array and transpose into a column array
*              % input a as a row array. Compute 3x3 matrix of pairwise products
[6,7,2;8,3,4]  % 2x3 matrix that picks elements from the former in column-major order
)              % apply index
d              % difference within each column


# Pyth, 16 bytes

-VF*VM.<VLQ_BMS2


Try it online: Demonstration

### Explanation:

-VF*VM.<VLQ_BMS2   Q = input, pair of vectors [u, v]
S2   creates the list [1, 2]
_BM     transforms it to [[1, -1], [2, -2]]
.<VLQ        rotate of the input vectors accordingly to the left:
[[u by 1, v by -1], [u by 2, v by -2]]
*VM             vectorized multiplication for each of the vector-pairs
-VF                vectorized subtraction of the resulting two vectors


# Jelly, 5 bytes

Takes input in the form $$\[[x_1,x_2],[y_1,y_2],[z_1,z_2]]\$$. If you want them to be two lists of x-y-z coordinates, just prepend Z to the beginning of the program.

ṁ4ÆḊƝ


Try it online!

Here is a PDF explanation in case SE markdown can't handle it.

### The cross-product in analytic form

Let $$\(x_1,y_1,z_1)\$$ be the coordinates of $$\\vec{v_1}\$$ and $$\(x_2,y_2,z_2)\$$ be the coordinates of $$\\vec{v_2}\$$. Their analytic expressions are as follows:

$$\boldsymbol{\vec{v_1}}=x_1\cdot \boldsymbol{\vec{i}}+y_1\cdot \boldsymbol{\vec{j}}+z_1\cdot\boldsymbol{\vec{k}}$$ $$\boldsymbol{\vec{v_2}}=x_2\cdot \boldsymbol{\vec{i}}+y_2\cdot \boldsymbol{\vec{j}}+z_2\cdot\boldsymbol{\vec{k}}$$

The only thing left to do now is to also write their cross-product in terms of its coordinates in the $$\Oxyz\$$ space.

$$\boldsymbol{\vec{v_1}}\times \boldsymbol{\vec{v_2}}=\left(x_1\cdot \boldsymbol{\vec{i}}+y_1\cdot \boldsymbol{\vec{j}}+z_1\cdot\boldsymbol{\vec{k}}\right)\times\left(x_2\cdot \boldsymbol{\vec{i}}+y_2\cdot \boldsymbol{\vec{j}}+z_2\cdot\boldsymbol{\vec{k}}\right)$$

Keeping in mind that: $$\boldsymbol{\vec{i}}\times \boldsymbol{\vec{j}}=\boldsymbol{\vec{k}}, \:\: \boldsymbol{\vec{i}}\times \boldsymbol{\vec{k}}=-\boldsymbol{\vec{j}}, \:\: \boldsymbol{\vec{j}}\times \boldsymbol{\vec{i}}=-\boldsymbol{\vec{k}}, \:\: \boldsymbol{\vec{j}}\times \boldsymbol{\vec{k}}=\boldsymbol{\vec{i}}, \:\: \boldsymbol{\vec{k}}\times \boldsymbol{\vec{i}}=\boldsymbol{\vec{j}}, \:\: \boldsymbol{\vec{k}}\times \boldsymbol{\vec{j}}=-\boldsymbol{\vec{i}}$$

After the necessary rearrangements and calculations:

$$\boldsymbol{\vec{v_1}}\times \boldsymbol{\vec{v_2}}=(y_1z_2-z_1y_2)\cdot \boldsymbol{\vec{i}}+(z_1x_2-x_1z_2)\cdot \boldsymbol{\vec{j}}+(x_1y_2-y_1x_2)\cdot \boldsymbol{\vec{k}}$$

### The close relationship with matrix determinants

There's an interesting thing to note here:

$$x_1y_2-y_1x_2=\left|\begin{matrix}x_1 & y_1 \\\ x_2 & y_2\end{matrix}\right|$$ $$z_1x_2-x_1z_2=\left|\begin{matrix}z_1 & x_1 \\\ z_2 & x_2\end{matrix}\right|$$ $$y_1z_2-z_1y_2=\left|\begin{matrix}y_1 & z_1 \\\ y_2 & z_2\end{matrix}\right|$$

Where we use the notation $$\\left|\cdot\right|\$$ for matrix determinant. Notice the beautiful rotational symmetry?

### Jelly code explanation

Well... not much to explain here. It just generates the matrix:

$$\left(\begin{matrix}x_1 & y_1 & z_1 & x_1 \\\ x_2 & y_2 & z_2 & x_2\end{matrix}\right)$$

And for each pair of neighbouring matrices, it computes the determinant of the matrix formed by joining the two.

ṁ4ÆḊƝ – Monadic Link. Takes input as [[x1,x2],[y1,y2],[z1,z2]].
ṁ4    – Mold 4. Cycle the list up to length 4, reusing the elements if necessary.
Generates [[x1,x2],[y1,y2],[z1,z2],[x1,x2]].
Ɲ – For each pair of neighbours: [[x1,x2],[y1,y2]], [[y1,y2],[z1,z2]], [[z1,z2],[x1,x2]].
ÆḊ  – Compute the determinant of those 2 paired together into a single matrix.


# K5, 444037 32 bytes

Wrote this one quite a while ago and dusted it off again recently.

{{x[y]-x[|y]}[*/x@']'3 3\'5 6 1}


In action:

 cross: {{x[y]-x[|y]}[*/x@']'3 3\'5 6 1};

cross (3 1 4;1 5 9)
-11 -23 14
cross (0.95972 0.25833 0.22140;0.93507 -0.80917 -0.99177)
-7.705371e-2 1.158846 -1.018133


## Edit 1:

Saved 4 bytes by taking input as a list of lists instead of two separate arguments:

old: {m:{*/x@'y}(x;y);{m[x]-m[|x]}'(1 2;2 0;0 1)}
new: {m:{*/x@'y}x    ;{m[x]-m[|x]}'(1 2;2 0;0 1)}


## Edit 2:

Saved 3 bytes by computing a lookup table with base-decode:

old: {m:{*/x@'y}x;{m[x]-m[|x]}'(1 2;2 0;0 1)}
new: {m:{*/x@'y}x;{m[x]-m[|x]}'3 3\'5 6 1}


## Edit 3:

Save 5 bytes by rearranging application to permit using a tacit definition instead of a local lambda. Unfortunately, this solution no longer works in oK, and requires the official k5 interpreter. Gonna have to take my word for this one until I fix the bug in oK:

old: {m:{*/x@'y}x;{m[x]-m[|x]}'3 3\'5 6 1}
new: {{x[y]-x[|y]}[*/x@']     '3 3\'5 6 1}


# Python, 73 48 bytes

Thanks @FryAmTheEggman

lambda (a,b,c),(d,e,f):[b*f-c*e,c*d-a*f,a*e-b*d]


This is based on the component definition of the vector cross product.

Try it here

• lambda (a,b,c),(d,e,f):... should save a lot. Commented Jan 30, 2016 at 3:09
• @FryAmTheEggman You are right. I forgot that lambda can specify how the argument should be. Commented Jan 30, 2016 at 3:12

# Ruby, 49 bytes

->u,v{(0..2).map{|a|u[a-2]*v[a-1]-u[a-1]*v[a-2]}}


Try it online!

Returning after 2 years, I shaved off 12 bytes by using how Ruby treats negative array indices. -1 is the last element of the array, -2 the second last etc.

# Ruby, 57

->u,v{(0..2).map{|a|u[b=(a+1)%3]*v[c=(a+2)%3]-u[c]*v[b]}}


In test program

f=->u,v{(0..2).map{|a|u[b=(a+1)%3]*v[c=(a+2)%3]-u[c]*v[b]}}

p f[[3, 1, 4], [1, 5, 9]]

p f[[5, 0, -3], [-3, -2, -8]]

p f[[0.95972, 0.25833, 0.22140],[0.93507, -0.80917, -0.99177]]

p f[[1024.28, -2316.39, 2567.14], [-2290.77, 1941.87, 712.09]]


# Wolfram Language (Mathematica), 38 33 25 24 bytes

-1 byte thanks to @att.

Det@{a={i,j,},##}~D~{a}&


Try it online!

• Surprised there be no builtin in Mathematica for this Commented Apr 9, 2023 at 0:38
• @Seggan The builtin is Cross. But this challenge says that builtins that specifically calculate the cross product are disallowed. Commented Apr 9, 2023 at 1:19
• -1 with Null as one of the units
– att
Commented Apr 9, 2023 at 4:09

## ES6, 40 bytes

(a,b,c,d,e,f)=>[b*f-c*e,c*d-a*f,a*e-b*d]


44 bytes if the input needs to be two arrays:

([a,b,c],[d,e,f])=>[b*f-c*e,c*d-a*f,a*e-b*d]


52 bytes for a more interesting version:

(a,b)=>a.map((_,i)=>a[x=++i%3]*b[y=++i%3]-a[y]*b[x])


# Julia 0.7, 45 39 bytes

f(a,b)=1:3 .|>i->det([eye(3)[i,:] a b])


Try it online!

Uses the determinant-based formula given in the task description.

Thanks to H.PWiz for -6 bytes.

• 39 bytes with two tricks: f(a,b)=1:3 .|>i->det([eye(3)[i,:] a b]) Commented Apr 20, 2019 at 1:45

# Pari/GP, 41 bytes

(a,b)->Vec(matdet(Mat([[x^2,x,1],a,b]~)))


Try it online!

# CSASM v2.5.0.2, 306 bytes

func a:
dup
dup
ldelem 0
pop $3 ldelem 1 pop$4
ldelem 2
pop $5 dup dup ldelem 0 pop$a
ldelem 1
pop $1 ldelem 2 pop$2
push $1 push$5
mul
push $2 push$4
mul
sub
push $2 push$3
mul
push $a push$5
mul
sub
push $a push$4
mul
push $1 push$3
mul
sub
push 3
newarr f32
pop $a push$a
swap
stelem 2
push $a swap stelem 1 push$a
swap
stelem 0
push $a ret end  The function a expects two ~arr:f32 arrays representing the two 3D vectors on the stack before calling it. $$\\vec a\$$ should be pushed to the stack first, then $$\\vec b\$$ should be pushed. This function leaves an ~arr:f32 array on the stack which corresponds to $$\\vec c\$$. Explanation: ; Input: two ~arr:f32 representing the two vectors func a: ; stack: [ a, b, c ], [ d, e, f ] ; These numbers represent the coordinates of the two vectors for an easier explanation ; Duplicate the second vector twice dup dup ; stack: [ a, b, c ], [ d, e, f ], [ d, e, f ], [ d, e, f ] ; Store the elements in the array to the pre-defined registers$3, $4 and$5
ldelem 0
pop $3 ldelem 1 pop$4
ldelem 2
pop $5 ; Duplicate the first vector twice dup dup ; stack: [ a, b, c ], [ a, b, c ], [ a, b, c ] ; Store the elements in the array to the pre-defined registers$a, $1 and$2
ldelem 0
pop $a ldelem 1 pop$1
ldelem 2
pop $2 ; Perform the algorithm: [ bf - ce, cd - af, ae - bd ] ;$a = a, $1 = b,$2 = c
; $3 = d,$4 = e, $5 = f ; bf - ce push$1
push $5 mul push$2
push $4 mul sub ; cd - af push$2
push $3 mul push$a
push $5 mul sub ; ae - bd push$a
push $4 mul push$1
push $3 mul sub ; Create the result array and store it in$a
push 3
newarr f32
pop $a ; Store the resulting values from earlier into this new array ; "swap" swaps the top two values on the stack push$a
swap
stelem 2

push $a swap stelem 1 push$a
swap
stelem 0

push \$a
ret
end


## TI-BASIC, 757371 62 bytes

-4 bytes thanks to @MarcMush
-9 bytes using Ans instead of Prompt  and Disp

Not 62 characters -- TI-BASIC is tokenized.

:Prompt A
:{Ans(2)ʟA(3)-Ans(3)ʟA(2),Ans(3)ʟA(1)-Ans(1)ʟA(3),Ans(1)ʟA(2)-Ans(2)ʟA(1


Usage example, computing $$\\langle 1,2,3\rangle\times\langle 0,1,0\rangle\$$:

{1,2,3}:pgrmXPROD
A=?{0,1,0}
{⁻3 0 1}

• you don't need to close parentheses, you can remove the last 2 characters Commented Aug 24, 2021 at 18:05
• I think you can golf two more bytes by using ʟA and ʟB link Commented Sep 3, 2021 at 8:48
• @MarcMush I didn't know about that! I didn't use named lists when I first wrote it because I wanted to use a list I could guarantee actually existed, but I'll have to test that and update this if it is shorter. Commented Sep 3, 2021 at 14:40

# MATLAB/Octave, 61 bytes.

Try it online!

f=@(a,b)[det([1,0,0;a;b]),det([0,1,0;a;b]),det([0,0,1;a;b])];


# Wolfram Language (Mathematica), 24 21 bytes

D/@HodgeDual[1##]&


Try it online!

 is \[TensorWedge] (U+F3DB).

# APL(NARS), 23 chars, 46 bytes

{((1⌽⍺)×5⌽⍵)-(5⌽⍺)×1⌽⍵}


test:

  f←{((1⌽⍺)×5⌽⍵)-(5⌽⍺)×1⌽⍵}
(3 1 4) f (1 5 9)
¯11 ¯23 14
(5 0 ¯3) f (¯3 ¯2 ¯8)
¯6 49 ¯10
(0.95972 0.25833 0.22140) f (0.93507 ¯0.80917 ¯0.99177)
¯0.0770537061 1.158846002 ¯1.018133265
(1024.28 ¯2316.39 2567.14) f (¯2290.77 1941.87 712.09)
¯6634530.307 ¯6610106.843 ¯3317298.117