3
votes

I have three matrices, A is 2 by 3, B is 2 by 5 and Index is 3 by 5.

A = [1,3,5;2,4,6];
B = [5,3,3,5,3;6,4,4,6,4];
Index = logical([0,0,0,0,1;0,1,1,0,0;1,0,0,1,0]);

I am trying to see if each column vector in B matches with the correct column vector in A found by the index. The code I have is below.

error = 0;
for i = 1:size(B,2)
    if A(:,Index(:,i)) ~= B(:,i)
        error = error + 1;
    end
end

error will be 1 at the end of this loop because the last column in B should've been [1;2]. My problem is for very large(10^6) length of B and Index, this becomes very slow. Is there a way I can avoid the for loop or am I doomed?

1

1 Answers

4
votes

You can construct the indexed matrix upfront with A*Index and then test the two matrices directly:

>> error = sum(max(A*Index ~= B))

error =

     1

Details

Broken down, A*Index generates the indexed matrix:

>> A*Index

ans =

     5     3     3     5     1
     6     4     4     6     2

Which can then be compared directly with B:

>> A*Index ~= B

ans =

  2×5 logical array

   0   0   0   0   1
   0   0   0   0   1

Timings

With 10 million indexes, R2021a Online runs the vectorized version in ~1 sec vs ~100 sec for the loop:

>> B = repmat(B, 1, 1e7);
>> Index = repmat(Index, 1, 1e7);
>> tic
   error = sum(max(A*Index ~= B));
   toc

Elapsed time is 0.952846 seconds.
>> tic
   error = 0
   for i = 1:size(B,2)
       if A(:,Index(:,i)) ~= B(:,i)
           error = error + 1;
       end               
   end                           
   toc

Elapsed time is 98.666943 seconds.