natalie.petrov
natalie.petrov

Reputation: 59

Calculate the sum of each diagonal of a matrix

I have a matrix like A and I want to calculate the sum of each diagonal of this matrix and show it in a vector like Y.

A=[1 2 3; 4 5 6; 7 8 9]

Y=[3 8 15 12 7]

I know the code

[sum(diag(y,2)),sum(diag(y,1)),sum(diag(y,0)),sum(diag (y,-1)),sum(diag (y,-2))]

but i want to write it as a function.

Upvotes: 3

Views: 1621

Answers (3)

gnovice
gnovice

Reputation: 125854

Similar to the answer from rahnema1, you can also generate your indices using toeplitz before applying accumarray:

[r, c] = size(A);
index = toeplitz(c:(r+c-1), c:-1:1);
Y = accumarray(index(:), A(:)).';

Upvotes: 1

rahnema1
rahnema1

Reputation: 15837

Here is a possible solution:

[r ,c]=size(A);
idx=bsxfun(@plus,(r:-1:1)',0:c-1);
s=flipud(accumarray(idx(:),A(:)));

Comparing this with spdiags that proposed in other answer this method performs much much better in Octave. Benchmark:

A = rand(1000);
disp('---------bsxfun+accumarray----------')
tic
    [r ,c]=size(A);
    idx=bsxfun(@plus,(r:-1:1)',0:c-1);
    s=flipud(accumarray(idx(:),A(:)));
toc
disp('---------spdiags----------')
tic
    dsum = fliplr(sum(spdiags(A)));
toc

Result:

---------bsxfun+accumarray----------
Elapsed time is 0.0114651 seconds.
---------spdiags----------
Elapsed time is 8.62041 seconds.

Upvotes: 3

obchardon
obchardon

Reputation: 10792

spdiags can do exactly what you want:

dsum = sum(spdiags(A))

You can reverse the vector with fliplr and create a function:

function dsum = diagsum(A)
    dsum = fliplr(sum(spdiags(A)));
end

RESULT

dsum =

    3    8   15   12    7

Upvotes: 5

Related Questions