/**
   * accumulates per-segment multi-valued facet counts, mapping to global ordinal space on-the-fly
   */
  static void accumMultiGeneric(
      int counts[],
      int startTermIndex,
      SortedSetDocValues si,
      DocIdSetIterator disi,
      int subIndex,
      OrdinalMap map)
      throws IOException {
    final LongValues ordMap = map == null ? null : map.getGlobalOrds(subIndex);
    int doc;
    while ((doc = disi.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
      si.setDocument(doc);
      // strange do-while to collect the missing count (first ord is NO_MORE_ORDS)
      int term = (int) si.nextOrd();
      if (term < 0) {
        if (startTermIndex == -1) {
          counts[0]++; // missing count
        }
        continue;
      }

      do {
        if (map != null) {
          term = (int) ordMap.get(term);
        }
        int arrIdx = term - startTermIndex;
        if (arrIdx >= 0 && arrIdx < counts.length) counts[arrIdx]++;
      } while ((term = (int) si.nextOrd()) >= 0);
    }
  }
  /** folds counts in segment ordinal space (segCounts) into global ordinal space (counts) */
  static void migrateGlobal(int counts[], int segCounts[], int subIndex, OrdinalMap map) {
    final LongValues ordMap = map.getGlobalOrds(subIndex);
    // missing count
    counts[0] += segCounts[0];

    // migrate actual ordinals
    for (int ord = 1; ord < segCounts.length; ord++) {
      int count = segCounts[ord];
      if (count != 0) {
        counts[1 + (int) ordMap.get(ord - 1)] += count;
      }
    }
  }
 /**
  * accumulates per-segment single-valued facet counts, mapping to global ordinal space on-the-fly
  */
 static void accumSingleGeneric(
     int counts[],
     int startTermIndex,
     SortedDocValues si,
     DocIdSetIterator disi,
     int subIndex,
     OrdinalMap map)
     throws IOException {
   final LongValues ordmap = map == null ? null : map.getGlobalOrds(subIndex);
   int doc;
   while ((doc = disi.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
     int term = si.getOrd(doc);
     if (map != null && term >= 0) {
       term = (int) ordmap.get(term);
     }
     int arrIdx = term - startTermIndex;
     if (arrIdx >= 0 && arrIdx < counts.length) counts[arrIdx]++;
   }
 }
 @Override
 public int advance(int target) throws IOException {
   for (int docID = approximationScorer.advance(target);
       docID < NO_MORE_DOCS;
       docID = approximationScorer.nextDoc()) {
     final long segmentOrd = values.getOrd(docID);
     if (segmentOrd != -1) {
       final long globalOrd = segmentOrdToGlobalOrdLookup.get(segmentOrd);
       if (foundOrds.get(globalOrd)) {
         return docID;
       }
     }
   }
   return NO_MORE_DOCS;
 }
 @Override
 public int advance(int target) throws IOException {
   for (int docID = approximationScorer.advance(target);
       docID < NO_MORE_DOCS;
       docID = approximationScorer.nextDoc()) {
     final long segmentOrd = values.getOrd(docID);
     if (segmentOrd != -1) {
       final int globalOrd = (int) segmentOrdToGlobalOrdLookup.get(segmentOrd);
       if (collector.match(globalOrd)) {
         score = collector.score(globalOrd);
         return docID;
       }
     }
   }
   return NO_MORE_DOCS;
 }