docs: public static void quickSelect(ArrayModifiableDBIDs data, Comparator<? super DBIDRef> comparator, int start, int end, int rank) {
      DBIDArrayIter refi = data.iter(), refj = data.iter(), pivot = data.iter();
      while(true) {
        // Optimization for small arrays
        // This also ensures a minimum size below
        if(start + SMALL > end) {
          insertionSort(data, comparator, start, end, refi, refj);
          return;
        }
  
        // Best of 5 pivot picking:
        // Choose pivots by looking at five candidates.
        final int len = end - start;
        final int seventh = (len >> 3) + (len >> 6) + 1;
        final int m3 = (start + end) >> 1; // middle
        final int m2 = m3 - seventh;
        final int m1 = m2 - seventh;
        final int m4 = m3 + seventh;
        final int m5 = m4 + seventh;
  
        // Explicit (and optimal) sorting network for 5 elements
        // See Knuth for details.
        if(comparator.compare(refi.seek(m1), refj.seek(m2)) > 0) {
          data.swap(m1, m2);
        }
        if(comparator.compare(refi.seek(m1), refj.seek(m3)) > 0) {
          data.swap(m1, m3);
        }
        if(comparator.compare(refi.seek(m2), refj.seek(m3)) > 0) {
          data.swap(m2, m3);
        }
        if(comparator.compare(refi.seek(m4), refj.seek(m5)) > 0) {
          data.swap(m4, m5);
        }
        if(comparator.compare(refi.seek(m1), refj.seek(m4)) > 0) {
          data.swap(m1, m4);
        }
        if(comparator.compare(refi.seek(m3), refj.seek(m4)) > 0) {
          data.swap(m3, m4);
        }
        if(comparator.compare(refi.seek(m2), refj.seek(m5)) > 0) {
          data.swap(m2, m5);
        }
        if(comparator.compare(refi.seek(m2), refj.seek(m3)) > 0) {
          data.swap(m2, m3);
        }
        if(comparator.compare(refi.seek(m4), refj.seek(m5)) > 0) {
          data.swap(m4, m5);
        }
  
        int best = bestPivot(rank, m1, m2, m3, m4, m5);
        // Move middle element out of the way.
        data.swap(best, end - 1);
        pivot.seek(end - 1);
  
        // Begin partitioning
        int i = start, j = end - 2;
        // This is classic quicksort stuff
        while(true) {
          while(i <= j && comparator.compare(refi.seek(i), pivot) <= 0) {
            i++;
          }
          while(j >= i && comparator.compare(refj.seek(j), pivot) >= 0) {
            j--;
          }
          if(i >= j) {
            break;
          }
          data.swap(i, j);
        }
  
        // Move pivot (former middle element) back into the appropriate place
        data.swap(i, end - 1);
  
        // In contrast to quicksort, we only need to recurse into the half we are
        // interested in. Instead of recursion we now use iteration.
  
        pivot.seek(i); // Pivot has moved.
        // Skip duplicates to narrow down the search interval:
        while(rank < i && comparator.compare(refi.seek(i - 1), pivot) == 0) {
          --i;
        }
        while(rank > i && comparator.compare(refi.seek(i + 1), pivot) == 0) {
          ++i;
        }
        if(rank < i) {
          end = i;
        }
        else if(rank > i) {
          start = i + 1;
        }
        else {
          break;
        }
      } // Loop until rank==i
    }