title: Matlab histc with vector bins
body: <p>If I have two matrices A and B of size [m x n] and [p x n], and I want to find the counts of the number of times each row of B appears in A, for example:</p>
  
  <pre><code>&gt;&gt; A = rand(5,3)
  
  A =
  
      0.1419    0.6557    0.7577
      0.4218    0.0357    0.7431
      0.9157    0.8491    0.3922
      0.7922    0.9340    0.6555
      0.9595    0.6787    0.1712
  
  &gt;&gt; B = [A(2,:); A(1,:); A(2,:); A(3,:); A(3,:); A(4,:); A(5,:)] 
  
  B =
  
      0.4218    0.0357    0.7431
      0.1419    0.6557    0.7577
      0.4218    0.0357    0.7431
      0.9157    0.8491    0.3922
      0.9157    0.8491    0.3922
      0.7922    0.9340    0.6555
      0.9595    0.6787    0.1712
  </code></pre>
  
  <p>with the answer in this case being</p>
  
  <pre><code>ans =
  
       1     2     2     1     1
  </code></pre>
  
  <p>although unlike this example, in general m >> p</p>
  
  <p>If A and B were vectors matlab's histc would do the job, but there doesn't seem to be an equivalent if the bins are vectors.</p>
  
  <p>Currently I do it by:</p>
  
  <pre><code>for i=1:length(B)
      indices(i) = find(abs(A/B(i,:)-1) &lt; 1e-15); 
      % division requires a tolerance due to numerical issues
  end
  histc(indices, 1:size(A,1))
  
  ans =
  
       1     2     2     1     1
  </code></pre>
  
  <p>but since I have many such matrices B, and both A and B are large, this is horribly slow. Any ideas how to improve on this?</p>
  
  <p>EDIT:</p>
  
  <p>Looking at the methods so far, I have the following data:</p>
  
  <pre><code>A                    7871139x3                188907336  double                       
  B                        902x3                    21648  double                       
  </code></pre>
  
  <p>To make things quicker I'm just going to use the first 10 rows of B</p>
  
  <pre><code>B = B(1:10,:);
  </code></pre>
  
  <p>Note that for the full application I (currently) have >10^4 of such matrices (this will eventually be >10^6 ....)</p>
  
  <p>My first method:</p>
  
  <pre><code>tic, C = get_vector_index(A,B); toc
  Elapsed time is 36.630107 seconds.
  </code></pre>
  
  <p>bdecaf's method (can be reduced to ~25 seconds by removing the <code>if</code> statement and using L1 distance instead of L2 distance)</p>
  
  <pre><code>&gt;&gt; tic, C1 = get_vector_index(A,B); toc
  Elapsed time is 28.957243 seconds.
  &gt;&gt; isequal(C, C1) 
  
  ans =
  
       1
  </code></pre>
  
  <p>oli's pdist2 method</p>
  
  <pre><code>&gt;&gt; tic, C2 = get_vector_index(A,B); toc
  Elapsed time is 7.244965 seconds.
  
  &gt;&gt; isequal(C,C2)
  
  ans =
  
       1
  </code></pre>
  
  <p>oli's normalisation method</p>
  
  <pre><code>&gt;&gt; tic, C3 = get_vector_index(A,B); toc
  Elapsed time is 3.756682 seconds.
  
  &gt;&gt; isequal(C,C3)
  
  ans =
  
       1
  </code></pre>
  
  <p>Finally I came up with another method, where I search the first column, then I search the second column within the hits of the first column, recursing until the columns are exhausted. This is the fastest so far ....</p>
  
  <pre><code>N = size(A,2);
  loc = zeros(size(B,1),1);
  for i=1:size(B,1)
      idx{1} = find(A(:,1)==B(i,1));
      for k=2:N, 
          idx{k} = idx{k-1}(find(A(idx{k-1},k)==B(i,k))); 
      end
      loc(i) = idx{end};
  end
  C = histc(loc, 1:size(A,1));
  </code></pre>
  
  <p>which results in:</p>
  
  <pre><code>&gt;&gt; tic, C4 = get_vector_index(A,B); toc
  Elapsed time is 1.314370 seconds.
  
  &gt;&gt; isequal(C, C4)
  
  ans =
  
       1
  </code></pre>
  
  <p>Also note that using <code>intersect</code> is much slower:</p>
  
  <pre><code>&gt;&gt; tic, [~,IA] = intersect(A,B,'rows'); C5 = histc(IA,1:size(A,1)); toc
  Elapsed time is 44.392593 seconds.
  
  &gt;&gt; isequal(C,C5)
  
  ans = 
  
      1
  </code></pre>