/** {@inheritDoc} */
  @Override
  public void updateTypeSpecificStats(NamedList stv) {
    if (computeSum) {
      sum += ((Number) stv.get("sum")).doubleValue();
    }
    if (computeSumOfSquares) {
      sumOfSquares += ((Number) stv.get("sumOfSquares")).doubleValue();
    }

    if (computePercentiles) {
      byte[] data = (byte[]) stv.get("percentiles");
      ByteBuffer buf = ByteBuffer.wrap(data);
      tdigest.add(AVLTreeDigest.fromBytes(buf));
    }
  }
 /** {@inheritDoc} */
 @Override
 public void updateTypeSpecificStats(Number v, int count) {
   double value = v.doubleValue();
   if (computeSumOfSquares) {
     sumOfSquares += (value * value * count); // for std deviation
   }
   if (computeSum) {
     sum += value * count;
   }
   if (computePercentiles) {
     tdigest.add(value, count);
   }
 }
 /**
  * Adds sum, sumOfSquares, mean, stddev, and percentiles to the given NamedList
  *
  * @param res NamedList to add the type specific statistics too
  */
 @Override
 protected void addTypeSpecificStats(NamedList<Object> res) {
   if (statsField.includeInResponse(Stat.sum)) {
     res.add("sum", sum);
   }
   if (statsField.includeInResponse(Stat.sumOfSquares)) {
     res.add("sumOfSquares", sumOfSquares);
   }
   if (statsField.includeInResponse(Stat.mean)) {
     res.add("mean", sum / count);
   }
   if (statsField.includeInResponse(Stat.stddev)) {
     res.add("stddev", getStandardDeviation());
   }
   if (statsField.includeInResponse(Stat.percentiles)) {
     if (statsField.getIsShard()) {
       // as of current t-digest version, smallByteSize() internally does a full conversion in
       // order to determine what the size is (can't be precomputed?) .. so rather then
       // serialize to a ByteBuffer twice, allocate the max possible size buffer,
       // serialize once, and then copy only the byte[] subset that we need, and free up the buffer
       ByteBuffer buf = ByteBuffer.allocate(tdigest.byteSize()); // upper bound
       tdigest.asSmallBytes(buf);
       res.add("percentiles", Arrays.copyOf(buf.array(), buf.position()));
     } else {
       NamedList<Object> percentileNameList = new NamedList<Object>();
       for (Double percentile : statsField.getPercentilesList()) {
         // Empty document set case
         if (tdigest.size() == 0) {
           percentileNameList.add(percentile.toString(), null);
         } else {
           Double cutoff = tdigest.quantile(percentile / 100);
           percentileNameList.add(percentile.toString(), cutoff);
         }
       }
       res.add("percentiles", percentileNameList);
     }
   }
 }