docs: private boolean kNNABOD(Database db, Relation<V> relation, DBIDs ids, WritableDoubleDataStore abodvalues, DoubleMinMax minmaxabod) {
      DistanceQuery<V> dq = db.getDistanceQuery(relation, SquaredEuclideanDistanceFunction.STATIC);
      KNNQuery<V> knnq = db.getKNNQuery(dq, DatabaseQuery.HINT_OPTIMIZED_ONLY);
      boolean squared = true;
      if(knnq == null) {
        dq = db.getDistanceQuery(relation, EuclideanDistanceFunction.STATIC);
        knnq = db.getKNNQuery(dq, DatabaseQuery.HINT_OPTIMIZED_ONLY);
        if(knnq == null) {
          return false;
        }
        squared = false;
      }
      SimilarityQuery<V> lk = db.getSimilarityQuery(relation, LinearKernelFunction.STATIC);
      int k1 = k + 1; // We will get the query point back by the knnq.
  
      MeanVariance s = new MeanVariance();
      for(DBIDIter pA = ids.iter(); pA.valid(); pA.advance()) {
        KNNList nl = knnq.getKNNForDBID(pA, k1);
        double simAA = lk.similarity(pA, pA);
  
        s.reset();
        DoubleDBIDListIter iB = nl.iter(), iC = nl.iter();
        for(; iB.valid(); iB.advance()) {
          double dAB = iB.doubleValue();
          double simAB = lk.similarity(pA, iB);
          if(!(dAB > 0.)) {
            continue;
          }
          for(iC.seek(iB.getOffset() + 1); iC.valid(); iC.advance()) {
            double dAC = iC.doubleValue();
            double simAC = lk.similarity(pA, iC);
            if(!(dAC > 0.)) {
              continue;
            }
            // Exploit bilinearity of scalar product:
            // <B-A, C-A> = <B, C-A> - <A,C-A>
            // = <B,C> - <B,A> - <A,C> + <A,A>
            double simBC = lk.similarity(iB, iC);
            double numerator = simBC - simAB - simAC + simAA;
            if(squared) {
              double div = 1. / (dAB * dAC);
              s.put(numerator * div, FastMath.sqrt(div));
            }
            else {
              double sqrtdiv = 1. / (dAB * dAC);
              s.put(numerator * sqrtdiv * sqrtdiv, sqrtdiv);
            }
          }
        }
        final double abof = s.getNaiveVariance();
        minmaxabod.put(abof);
        abodvalues.putDouble(pA, abof);
      }
      return true;
    }