Use Perl PDL to rotate a matrix

791 Views Asked by At

I would like to use Perl and PDL to achieve a rotation of a 3x3 matrix (if possible)

I.e original matrix

[ 1, 2, 3 ]
[ 4, 5, 6 ]
[ 7, 8, 9 ]

I would like to rotate, around 5, so it becomes new matrix

[ 3, 6, 9 ]
[ 2, 5, 8 ]
[ 1, 4, 7 ]

Effectively this is the same as How do you rotate a two dimensional array? but I'd like to use Perl and PDL.

Thanks for your help up front.

3

There are 3 best solutions below

2
On BEST ANSWER

Perhaps not the most optimized way to do it:

pdl> $m = sequence(3,3)+1
pdl> p $m

[
 [1 2 3]
 [4 5 6]
 [7 8 9]
]

pdl> p $m->transpose->slice( ':', '-1:0' )

[
 [3 6 9]
 [2 5 8]
 [1 4 7]
]
0
On

More stupid matrix tricks

I'm not conversant in PDL either, but if you can "slice" the 2d matrix to a "virtual", 9 element vector, which looks possible in a cursory read of the documentation, then you can implement any permutation (including rotation) of the original 3x3 as a 9x9 permutation matrix, multiply the 1d slice by this matrix, and then refer to the original 3x3 pdl to see the result.

If I have some time I will try to learn enough of PDL to test this idea.

0
On

Stupid Matrix Tricks

This might not be the answer you were looking for, but I think it's interesting. It's a purely mathematical solution since my pdl skills are piddling (ha! I bet everyone uses that joke) and as such I haven't done any benchmarking to see if it's even any faster than a double loop.

Let's define a matrix W like so:

    [0 0 1]
W = [0 1 0]
    [1 0 0]

W is the swap matrix. (Don't know why I called it W instead of S, but there you go.) If you have a another 3x3 matrix M and multiply W x M, it swaps the rows of M. If you multiply M x W (changing the order), it swaps the columns of M.

Using your matrix above we can swap the rows like so:

        [0 0 1]   [1 2 3]   [7 8 9]
W x M = [0 1 0] x [4 5 6] = [4 5 6]
        [1 0 0]   [7 8 9]   [1 2 3]

So to rotate the original matrix 90° counterclockwise we know we need to transpose it and then swap rows (M' is M-transpose):

         [0 0 1]   [1 4 7]   [3 6 9]
W x M' = [0 1 0] x [2 5 8] = [2 5 8]
         [1 0 0]   [3 6 9]   [1 4 7]

As I said before, multiplying M x W will swap the columns of M:

        [1 2 3]   [0 0 1]   [3 2 1]
M x W = [4 5 6] x [0 1 0] = [6 5 4]
        [7 8 9]   [1 0 0]   [9 8 7]

Which just happens to be the transpose of the previous result W x M'! Taking the final step, we have:

         [1 4 7]   [0 0 1]   [7 4 1]
M' x W = [2 5 8] x [0 1 0] = [8 5 2]
         [3 6 9]   [1 0 0]   [9 6 3]

Now we've rotated M 90° clockwise. But this is just the transpose of our original result W x M.

For our 90° rotations we then have two ways to generate each result:

Rotate counterclockwise: W  x M' = (M x W)'  
Rotate clockwise:        M' x W  = (W x M)'

Finally, for the sake of completeness, to rotate the matrix 180° you swap both the rows and the columns:

            [0 0 1]   [1 2 3]   [0 0 1]   [7 8 9]   [0 0 1]   [9 8 7]
W x M x W = [0 1 0] x [4 5 6] x [0 1 0] = [4 5 6] x [0 1 0] = [6 5 4]
            [1 0 0]   [7 8 9]   [1 0 0]   [1 2 3]   [1 0 0]   [3 2 1]

Well, I guess it's not totally complete since we can also do reflections and rotations of reflections as well using the swap matrix and matrix transposes, but we'll leave it there for now.