func (t *TDigest) Add(value float64) error {
	return t.AddWeighted(value, 1)
}
Add is an alias for AddWeighted(x,1)
Read the documentation for AddWeighted for more details.
package tdigest
import (
	"fmt"
	"math"
)
type TDigest struct {
	summary     *summary
	compression float64
	count       uint64
	rng         RNG
}
func New(options ...tdigestOption) (*TDigest, error) {
	tdigest, err := newWithoutSummary(options...)
	if err != nil {
		return nil, err
	}
	tdigest.summary = newSummary(estimateCapacity(tdigest.compression))
	return tdigest, nil
}
func newWithoutSummary(options ...tdigestOption) (*TDigest, error) {
	tdigest := &TDigest{
		compression: 100,
		count:       0,
		rng:         newLocalRNG(1),
	}
	for _, option := range options {
		err := option(tdigest)
		if err != nil {
			return nil, err
		}
	}
	return tdigest, nil
}
func _quantile(index float64, previousIndex float64, nextIndex float64, previousMean float64, nextMean float64) float64 {
	delta := nextIndex - previousIndex
	previousWeight := (nextIndex - index) / delta
	nextWeight := (index - previousIndex) / delta
	return previousMean*previousWeight + nextMean*nextWeight
}
func (t *TDigest) Compression() float64 {
	return t.compression
}
func (t *TDigest) Quantile(q float64) float64 {
	if q < 0 || q > 1 {
		panic("q must be between 0 and 1 (inclusive)")
	}
	if t.summary.Len() == 0 {
		return math.NaN()
	} else if t.summary.Len() == 1 {
		return t.summary.Mean(0)
	}
	index := q * float64(t.count-1)
	previousMean := math.NaN()
	previousIndex := float64(0)
	next, total := t.summary.FloorSum(index)
	if next > 0 {
		previousMean = t.summary.Mean(next - 1)
		previousIndex = total - float64(t.summary.Count(next-1)+1)/2
	}
	for {
		nextIndex := total + float64(t.summary.Count(next)-1)/2
		if nextIndex >= index {
			if math.IsNaN(previousMean) {
				if nextIndex == previousIndex {
					return t.summary.Mean(next)
				}
				nextIndex2 := total + float64(t.summary.Count(next)) + float64(t.summary.Count(next+1)-1)/2
				previousMean = (nextIndex2*t.summary.Mean(next) - nextIndex*t.summary.Mean(next+1)) / (nextIndex2 - nextIndex)
			}
			return _quantile(index, previousIndex, nextIndex, previousMean, t.summary.Mean(next))
		} else if next+1 == t.summary.Len() {
			nextIndex2 := float64(t.count - 1)
			nextMean2 := (t.summary.Mean(next)*(nextIndex2-previousIndex) - previousMean*(nextIndex2-nextIndex)) / (nextIndex - previousIndex)
			return _quantile(index, nextIndex, nextIndex2, t.summary.Mean(next), nextMean2)
		}
		total += float64(t.summary.Count(next))
		previousMean = t.summary.Mean(next)
		previousIndex = nextIndex
		next++
	}
}
func boundedWeightedAverage(x1 float64, w1 float64, x2 float64, w2 float64) float64 {
	if x1 > x2 {
		x1, x2, w1, w2 = x2, x1, w2, w1
	}
	result := (x1*w1 + x2*w2) / (w1 + w2)
	return math.Max(x1, math.Min(result, x2))
}
func (t *TDigest) AddWeighted(value float64, count uint64) (err error) {
	if count == 0 {
		return fmt.Errorf("Illegal datapoint <value: %.4f, count: %d>", value, count)
	}
	if t.summary.Len() == 0 {
		err = t.summary.Add(value, count)
		t.count = uint64(count)
		return err
	}
	begin := t.summary.Floor(value)
	if begin == -1 {
		begin = 0
	}
	begin, end := t.findNeighbors(begin, value)
	closest := t.chooseMergeCandidate(begin, end, value, count)
	if closest == t.summary.Len() {
		err = t.summary.Add(value, count)
		if err != nil {
			return err
		}
	} else {
		c := float64(t.summary.Count(closest))
		newMean := boundedWeightedAverage(t.summary.Mean(closest), c, value, float64(count))
		t.summary.setAt(closest, newMean, uint64(c)+count)
	}
	t.count += uint64(count)
	if float64(t.summary.Len()) > 20*t.compression {
		err = t.Compress()
	}
	return err
}
func (t TDigest) Count() uint64 {
	return t.count
}