docs: protected void computeAverageChainingDistances(KNNQuery<O> knnq, DistanceQuery<O> dq, DBIDs ids, WritableDoubleDataStore acds) {
      FiniteProgress lrdsProgress = LOG.isVerbose() ? new FiniteProgress("Computing average chaining distances", ids.size(), LOG) : null;
  
      // Compute the chaining distances.
      // We do <i>not</i> bother to materialize the chaining order.
      for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
        final KNNList neighbors = knnq.getKNNForDBID(iter, k);
        final int r = neighbors.size();
        DoubleDBIDListIter it1 = neighbors.iter(), it2 = neighbors.iter();
        // Store the current lowest reachability.
        final double[] mindists = new double[r];
        for(int i = 0; it1.valid(); it1.advance(), ++i) {
          mindists[i] = DBIDUtil.equal(it1, iter) ? Double.NaN : it1.doubleValue();
        }
  
        double acsum = 0.;
        for(int j = ((r < k) ? r : k) - 1; j > 0; --j) {
          // Find the minimum:
          int minpos = -1;
          double mindist = Double.NaN;
          for(int i = 0; i < mindists.length; ++i) {
            double curdist = mindists[i];
            // Both values could be NaN, deliberately.
            if(curdist == curdist && !(curdist > mindist)) {
              minpos = i;
              mindist = curdist;
            }
          }
          acsum += mindist * j; // Weighted sum, decreasing weights
          mindists[minpos] = Double.NaN;
          it1.seek(minpos);
          // Update distances
          it2.seek(0);
          for(int i = 0; it2.valid(); it2.advance(), ++i) {
            final double curdist = mindists[i];
            if(curdist != curdist) {
              continue; // NaN = processed!
            }
            double newdist = dq.distance(it1, it2);
            if(newdist < curdist) {
              mindists[i] = newdist;
            }
          }
        }
        acds.putDouble(iter, acsum / (r * 0.5 * (r - 1.)));
        LOG.incrementProcessed(lrdsProgress);
      }
      LOG.ensureCompleted(lrdsProgress);
    }