public int remap(int oldDocID) {
    if (oldDocID < minDocID)
      // Unaffected by merge
      return oldDocID;
    else if (oldDocID >= maxDocID)
      // This doc was "after" the merge, so simple shift
      return oldDocID - docShift;
    else {
      // Binary search to locate this document & find its new docID
      int lo = 0;                                      // search starts array
      int hi = docMaps.length - 1;                  // for first element less

      while (hi >= lo) {
        int mid = (lo + hi) >>> 1;
        int midValue = starts[mid];
        if (oldDocID < midValue)
          hi = mid - 1;
        else if (oldDocID > midValue)
          lo = mid + 1;
        else {                                      // found a match
          while (mid+1 < docMaps.length && starts[mid+1] == midValue) {
            mid++;                                  // scan to last match
          }
          if (docMaps[mid] != null)
            return newStarts[mid] + docMaps[mid][oldDocID-starts[mid]];
          else
            return newStarts[mid] + oldDocID-starts[mid];
        }
      }
      if (docMaps[hi] != null)
        return newStarts[hi] + docMaps[hi][oldDocID-starts[hi]];
      else
        return newStarts[hi] + oldDocID-starts[hi];
    }
  }