Obtaining opposite diagonal of a matrix in Matlab

10,798

Solution 1

Here is my matrix, produced by A = magic(5)

A =

17    24     1     8    15
23     5     7    14    16
 4     6    13    20    22
10    12    19    21     3
11    18    25     2     9


s = size(A,1)
A(s:s-1:end-1)

ans =
11    12    13    14    15

Solution 2

Below is a comparison of all the methods mentioned so far, plus a few other variations I could think of. This was tested on 64-bit R2013a using TIMEIT function.

function [t,v] = testAntiDiag()
    % data and functions
    A = magic(5000);
    f = {
        @() func0(A) ;
        @() func1(A) ;
        @() func2(A) ;
        @() func3(A) ;
        @() func4(A) ;
        @() func5(A) ;
        @() func6(A) ;
        @() func7(A) ;
    };

    % timeit and check results
    t = cellfun(@timeit, f, 'UniformOutput',true);
    v = cellfun(@feval, f, 'UniformOutput',false);
    assert( isequal(v{:}) )
end


function d = func0(A)
    d = diag(A(end:-1:1,:));
end

function d = func1(A)
    d = diag(flipud(A));
end

function d = func2(A)
    d = flipud(diag(fliplr(A)));
end

function d = func3(A)
    d = diag(rot90(A,3));
end

function d = func4(A)
    n = size(A,1);
    d = A(n:n-1:end-1).';
end

function d = func5(A)
    n = size(A,1);
    d = A(cumsum(n + [0,repmat(-1,1,n-1)])).';
end

function d = func6(A)
    n = size(A,1);
    d = A(sub2ind([n n], n:-1:1, 1:n)).';
end

function d = func7(A)
    n = size(A,1);
    d = zeros(n,1);
    for i=1:n
        d(i) = A(n-i+1,i);
    end
end

The timings (in the same order they are defined above):

>> testAntiDiag
ans =
   0.078635867152801
   0.077895631970976    % @AlexR.
   0.080368641824528
   0.195832501156751
   0.000074983294297    % @thefourtheye
   0.000143019460665    % @woodchips
   0.000174679680437
   0.000152488508547    % for-loop

The most suprising result to me is the last one. Apparently JIT compilation is very effective on such simple for-loops.

Share:
10,798
Alex R.
Author by

Alex R.

Updated on June 21, 2022

Comments

  • Alex R.
    Alex R. almost 2 years

    Let A be an matrix of size [n,n]. If I want to extract its diagonal, I do diag(A).

    Actually, I want the opposite diagonal, which would be [A(n,1),A(n-1,2),A(n-2,3),...].

    One way to do this is via diag(flipud(A)). However, flipud(A) is quite wasteful and multiplies the time it takes by a factor of 10 compared to finding the usual diagonal.

    I'm looking for a fast way of obtaining the opposite diagonal. Naturally, for loops seem abysmally slow. Suggestions would be greatly appreciated.