Asked by Jason Tracey
on 21 Oct 2019

I am trying to insert small square matrices along the diagonal of a large matrix. These matrices are contained in a 3D array, and have different values. Overlapping values are to be added, and the small matrices are only inserted where they can fit fully inside the large matrix. The step dimension will always be equal to 1.

I have achieved an answer through the use of for-loops, but am attempting to vectorise this code for efficiency. How would I do this? The current, unvectorised code is shown below.

function M = TestDiagonal2()

N = 10;

n = 2;

maxRand = 3;

deepMiniM = randi(maxRand,n,n,N+1-n);

M = zeros(N);

for i = 1:N+1-n

M(i:i+1,i:i+1) = M(i:i+1,i:i+1) + deepMiniM(:,:,i);

end

end

The desired result is an `N`x`N` matrix with `n+1` diagonals populated:

3 1 0 0 0 0 0 0 0 0

4 5 3 0 0 0 0 0 0 0

0 3 3 3 0 0 0 0 0 0

0 0 1 6 3 0 0 0 0 0

0 0 0 4 4 4 0 0 0 0

0 0 0 0 2 3 2 0 0 0

0 0 0 0 0 2 6 2 0 0

0 0 0 0 0 0 4 2 2 0

0 0 0 0 0 0 0 3 3 1

0 0 0 0 0 0 0 0 3 3

Answer by Guillaume
on 21 Oct 2019

Note: I don't see how you can get a 4 at M(2, 1) if maxRand is 3.

Here is one way, no guarantee that it's faster than a loop. Works for any size of deepMiniM:

[rstart, cstart] = ndgrid(1:size(deepMiniM, 1), 1:size(deepMiniM, 2)); %destination indices of the first matrix

rall = rstart(:) + (0:N-size(deepMiniM, 1)); %destination indices of the rows of ALL the matrices

call = cstart(:) + (0:N-size(deepMiniM, 2)); %same for columns

M = accumarray([rall(:), call(:)], deepMiniM(:)); %pass destination and values to accumarray. Default accumarray function is sum

Sign in to comment.

Answer by Andrei Bobrov
on 21 Oct 2019

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Stephen Cobeldick (view profile)

## Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/486571-vectorisation-of-code-for-insertion-of-n-x-n-matrices-in-a-3d-array-along-the-diagonal-of-a-large-ma#comment_758609

Sign in to comment.