2
votes

Let's say I have a square matrix M:

M = [0 0 0 0 0 1 9; 0 0 0 0 0 4 4; 0 0 1 1 6 1 1; 0 1 2 9 2 1 0; 2 1 8 3 2 0 0; 0 8 1 1 0     0 0; 14 2 0 1 0 0 0]


      0 0 0 0 0 1 9
      0 0 0 0 0 4 4
      0 0 1 1 6 1 1
 M =  0 1 2 9 2 1 0
      2 1 8 3 2 0 0
      0 8 1 1 0 0 0
     14 2 0 1 0 0 0

Now I'd like to calculate two different cumulative sums: One that goes from the top of each column to the element of the column, that is a diagonal element of the matrix, and one that goes from the bottom of the column to the same diagonal element.

The resulting matrix M'should therefore be the following:

       0 0 0 0 0 1 9
       0 0 0 0 0 4 5
       0 0 1 1 6 2 1
 M' =  0 1 3 9 4 1 0
       2 2 8 5 2 0 0
       2 8 1 2 0 0 0
      14 2 0 1 0 0 0

I hope the explanation of what I'm trying to achieve is comprehensible enough. Since my matrices are much larger than the one in this example, the calculation should be efficient as well...but so far I couldn't even figure out how to calculate it "inefficiently".

2
Are your matrices always square? - horchler
yes they are always square - Schnigges
Would you mind clearing up "One that goes from the top of each column to the element of the column, that is a diagonal element of the matrix, and one that goes from the bottom of the column to the same diagonal element." I believe I have a solution, but this is confusing me. So it adds all the elements from the top of the column down to but excluding the diagonal, and same from the bottom up to but excluding the diagonal? - voxeloctree
Yeah, that sounds like the same thing...sorry for my imprecise explanation. If you get M' as an answer, it should be correct. - Schnigges
By the way, the elements running from the lower left to the upper right of a matrix are referred to as the anti-diagonal, as opposed to the diagonal that runs from the upper left to the lower right. - horchler

2 Answers

2
votes

In one line using some flipping and the upper triangular function triu:

Mp = fliplr(triu(fliplr(cumsum(M)),1)) ...
     +flipud(triu(cumsum(flipud(M)),1)) ...
     +flipud(diag(diag(flipud(M))));
1
votes

The following will do the job:

Mnew = fliplr(triu(cumsum(triu(fliplr(M)),1))) + flipud(triu(cumsum(triu(flipud(M)),1)));
Mnew = Mnew - fliplr(diag(diag(fliplr(Mnew)))) + fliplr(diag(diag(fliplr(M))));

But is it the fastest method?

I think logical indexing might get you there faster