Search code examples
matlabmatrixvectorvectorizationcross-product

Vector-defined cross product application matrix and vectorization in Matlab


I ran into an operation I cannot seem to achieve via vectorization.

Let's say I want to find the matrix of the application defined by

h: X -> cross(V,X)

where V is a predetermined vector (both X and V are 3-by-1 vectors).

In Matlab, I would do something like

M= cross(repmat(V,1,3),eye(3,3)) 

to get this matrix. For instance, V=[1;2;3] yields

M =

 0    -3     2
 3     0    -1
-2     1     0

Let's now suppose that I have a 3-by-N matrix

V=[V_1,V_2...V_N]

with each column defining its own cross-product operation. For N=2, here's a naive try to find the two cross-product matrices that V's columns define

 V=[1,2,3;4,5,6]'
M=cross(repmat(V,1,3),repmat(eye(3,3),1,2))

results in

V =

     1     4
     2     5
     3     6


M =

     0    -6     2     0    -3     5
     3     0    -1     6     0    -4
    -2     4     0    -5     1     0

while I was expecting

M =

 0    -3     2     0    -6     5
 3     0    -1     6     0    -4
-2     1     0    -5     4     0

2 columns are inverted.

Is there a way to achieve this without for loops?

Thanks!


Solution

  • First, make sure you read the documentation of cross very carefully when dealing with matrices:

    It says:

    C = cross(A,B,DIM), where A and B are N-D arrays, returns the cross
    product of vectors in the dimension DIM of A and B. A and B must
    have the same size, and both SIZE(A,DIM) and SIZE(B,DIM) must be 3.
    

    Bear in mind that if you don't specify DIM, it's automatically assumed to be 1, so you're operating along the columns. In your first case, you specified both the inputs A and B to be 3 x 3 matrices. Therefore, the output will be the cross product of each column independently due to the assumption that DIM=1. As such, you expect that the i'th column of the output contains the cross product of the i'th column of A and the i'th column of B and the number of rows is expected to be 3 and the number of columns needs to match between A and B.

    You're getting what you expect because the first input A has [1;2;3] duplicated correctly over the columns three times. From your second piece of code, what you're expecting for V as the first input (A) looks like this:

    V =
    
         1     1     1     4     4     4
         2     2     2     5     5     5
         3     3     3     6     6     6
    

    However, when you do repmat, you are in fact alternating between each column. In fact, you are getting this:

    V = 
    
         1     4     1     4     1     4
         2     5     2     5     2     5
         3     6     3     6     3     6
    

    repmat tile matrices together and you specified that you wanted to tile V horizontally three times. That's obviously not correct. This explains why the columns are swapped because the second, fourth and sixth columns of V actually should appear at the last three columns instead. As such, the ordering of your input columns is the reason why the output appears swapped.

    As such, you need to re-order V so that the first three vectors are [1;2;3], followed by the next three vectors as [4;5;6] after. Therefore, you can generate your original V matrix first, then create a new matrix such that the odd column comes first in a group of three, followed by the even column in a group of three after:

    >> V = [1,2,3;4,5,6].';
    >> V = V(:, [1 1 1 2 2 2])
    
    V =
    
         1     1     1     4     4     4
         2     2     2     5     5     5
         3     3     3     6     6     6
    

    Now use V with cross and maintain the same second input:

    >> M = cross(V, repmat(eye(3), 1, 2))
    
    M =
    
         0    -3     2     0    -6     5
         3     0    -1     6     0    -4
        -2     1     0    -5     4     0
    

    Looks good to me!