Reputation: 106
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
Reputation: 112659
Just use 2D convolution (see conv2
).
M = conv2(eye(N-1), miniM);
m
×m
case, step 1 along each dimensionM = conv2(eye(N-size(miniM-1)+1), miniM);
m
×n
case, arbitrary steps along each dimensionIn 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