Search code examples
arraysmatlabindexing

Why is indexing via sub2ind not the same as indexing via A(i, j) in Matlab?


Assume that you have this matrix

>> P = zeros(8, 12)
P =

   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0

And you want to add 1 on each coordinate. If it's the same coordinate, it will be +1.

>> angles = [1 2 1 3 3 2 5 6 2 1 3 8]
angles =

   1   2   1   3   3   2   5   6   2   1   3   8

>> r = [1 2 4 2 5 6 1 4 6 6 3 6]
r =

   1   2   4   2   5   6   1   4   6   6   3   6

If I use sub2ind

>> indices = sub2ind(size(P), angles, r);
>> P(indices) = P(indices) + 1;
>> P
P =

   1   0   0   1   0   1   0   0   0   0   0   0
   0   1   0   0   0   1   0   0   0   0   0   0
   0   1   1   0   1   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   1   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   1   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   1   0   0   0   0   0   0

But if I using normal indexing

>> for k = 1:length(r)
      P(angles(k), r(k)) = P(angles(k), r(k)) + 1;
   end
>> P
P =

   1   0   0   1   0   1   0   0   0   0   0   0
   0   1   0   0   0   2   0   0   0   0   0   0
   0   1   1   0   1   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   1   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   1   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   1   0   0   0   0   0   0

If you look closely, there is a 2 inside the matrix P, but not inside the matrix P above.

Question:

Why does sub2ind indexing differ from regular P(i, j) indexing?


Solution

  • The difference arises because there is a pair of coordinates repeated (marked in boldface here):

    angles = [1 2 1 3 3 𝟐 5 6 𝟐 1 3 8]
    r =      [1 2 4 2 5 𝟔 1 4 𝟔 6 3 6]
    

    In the sub2ind version, the repeated pair of coordinates causes indices to have a repeated value. The line P(indices) = P(indices)+1; only adds 1 once to that entry of P. This is not related to ind2sub, it's just the way indexed assignment works: the changes are not "accumulated", so a repeated entry acts on the original value, without regard of previous occurrences of the same entry. For example:

    >> x = [10 20 30];
    ind = [2 3 3];
    x(ind) = x(ind)+1
    x =
        10    21    31
    

    Or, perhaps more clearly, note how the value 50 is useless here:

    >> x = [10 20 30];
    >> x([2 3 3]) = [40 50 60]
    x =
        10    40    60
    

    On the other hand, in the for version you explicitly accumulate the changes, so if an entry appears twice you add 1 twice to that entry.