Jason Tracey
Jason Tracey

Reputation: 106

Vectorisation of code for insertion of 2x2 matrix along the diagonal of a large matrix

I am trying to do an elementwise insertion of a small matrix (2x2) along the diagonal of a large matrix (10x10 say). Overlapping values are added, and the small matrix is only inserted where it can fit fully inside the large matrix.

I have achieved this using a for loop, but am curious whether the process can be vectorised.

function M = TestDiagonal()

N     = 10;
miniM = [1, -1; -1, 1];
M     = zeros(N);

for i = 1:N-1
    M(i:i+1,i:i+1) = M(i:i+1,i:i+1) + miniM;
end

end

Giving the desired matrix

 1    -1     0     0     0     0     0     0     0     0
-1     2    -1     0     0     0     0     0     0     0
 0    -1     2    -1     0     0     0     0     0     0
 0     0    -1     2    -1     0     0     0     0     0
 0     0     0    -1     2    -1     0     0     0     0
 0     0     0     0    -1     2    -1     0     0     0
 0     0     0     0     0    -1     2    -1     0     0
 0     0     0     0     0     0    -1     2    -1     0
 0     0     0     0     0     0     0    -1     2    -1
 0     0     0     0     0     0     0     0    -1     1

In the general case, the input will always be square, but can take any size. The step dimension will always be equal to 1.

Upvotes: 2

Views: 66

Answers (1)

Luis Mendo
Luis Mendo

Reputation: 112659

Just use 2D convolution (see conv2).

2×2 case, step 1 along each dimension

M = conv2(eye(N-1), miniM);

m×m case, step 1 along each dimension

M = conv2(eye(N-size(miniM-1)+1), miniM);

m×n case, arbitrary steps along each dimension

In this case the steps need to be defined:

step = [2 1]; % desired step along each dimension

and it makes more sense to define a desired number of repetitions R, rather than the final size (N), because the latter may not be achievable with full repetitions of miniM:

R = 4; % desired number of repetitions

Then:

M = conv2(full(sparse(1:step(1):step(1)*R, 1:step(2):step(2)*R, 1)), miniM);

Example:

>> miniM = [10 20 30; 40 50 60];
>> R = 4;
>> step = [1 2];
>> M = conv2(full(sparse(1:step(1):step(1)*R, 1:step(2):step(2)*R, 1)), miniM)
M =
    10    20    30     0     0     0     0     0     0
    40    50    70    20    30     0     0     0     0
     0     0    40    50    70    20    30     0     0
     0     0     0     0    40    50    70    20    30
     0     0     0     0     0     0    40    50    60

Upvotes: 3

Related Questions