func (s *summary) shuffle(rng RNG) {
	for i := len(s.means) - 1; i > 1; i-- {
		s.Swap(i, rng.Intn(i+1))
	}
}
Randomly shuffles summary contents, so they can be added to another summary
with being pathological. Renders summary invalid.
package tdigest
import (
	"fmt"
	"math"
	"sort"
)
type summary struct {
	means  []float64
	counts []uint64
}
func newSummary(initialCapacity int) *summary {
	s := &summary{
		means:  make([]float64, 0, initialCapacity),
		counts: make([]uint64, 0, initialCapacity),
	}
	return s
}
func (s *summary) Len() int {
	return len(s.means)
}
func (s *summary) Add(key float64, value uint64) error {
	if math.IsNaN(key) {
		return fmt.Errorf("Key must not be NaN")
	}
	if value == 0 {
		return fmt.Errorf("Count must be >0")
	}
	idx := s.findInsertionIndex(key)
	s.means = append(s.means, math.NaN())
	s.counts = append(s.counts, 0)
	copy(s.means[idx+1:], s.means[idx:])
	copy(s.counts[idx+1:], s.counts[idx:])
	s.means[idx] = key
	s.counts[idx] = value
	return nil
}
func (s *summary) findInsertionIndex(x float64) int {
	if len(s.means) < 250 {
		for i, mean := range s.means {
			if mean > x {
				return i
			}
		}
		return len(s.means)
	}
	return sort.Search(len(s.means), func(i int) bool {
		return s.means[i] > x
	})
}
func (s *summary) HeadSum(idx int) (sum float64) {
	return float64(sumUntilIndex(s.counts, idx))
}
func (s *summary) Floor(x float64) int {
	return s.findIndex(x) - 1
}
func (s *summary) findIndex(x float64) int {
	if len(s.means) < 250 {
		for i, mean := range s.means {
			if mean >= x {
				return i
			}
		}
		return len(s.means)
	}
	return sort.Search(len(s.means), func(i int) bool {
		return s.means[i] >= x
	})
}
func (s *summary) Mean(uncheckedIndex int) float64 {
	return s.means[uncheckedIndex]
}
func (s *summary) Count(uncheckedIndex int) uint64 {
	return s.counts[uncheckedIndex]
}
func (s *summary) FloorSum(sum float64) (index int, cumSum float64) {
	index = -1
	for i, count := range s.counts {
		if cumSum <= sum {
			index = i
		} else {
			break
		}
		cumSum += float64(count)
	}
	if index != -1 {
		cumSum -= float64(s.counts[index])
	}
	return index, cumSum
}
func (s *summary) setAt(index int, mean float64, count uint64) {
	s.means[index] = mean
	s.counts[index] = count
	s.adjustRight(index)
	s.adjustLeft(index)
}
func (s *summary) adjustRight(index int) {
	for i := index + 1; i < len(s.means) && s.means[i-1] > s.means[i]; i++ {
		s.means[i-1], s.means[i] = s.means[i], s.means[i-1]
		s.counts[i-1], s.counts[i] = s.counts[i], s.counts[i-1]
	}
}
func (s *summary) adjustLeft(index int) {
	for i := index - 1; i >= 0 && s.means[i] > s.means[i+1]; i-- {
		s.means[i], s.means[i+1] = s.means[i+1], s.means[i]
		s.counts[i], s.counts[i+1] = s.counts[i+1], s.counts[i]
	}
}
func (s *summary) ForEach(f func(float64, uint64) bool) {
	for i, mean := range s.means {
		if !f(mean, s.counts[i]) {
			break
		}
	}
}
func (s *summary) Perm(rng RNG, f func(float64, uint64) bool) {
	for _, i := range perm(rng, s.Len()) {
		if !f(s.means[i], s.counts[i]) {
			break
		}
	}
}
func (s *summary) Clone() *summary {
	return &summary{
		means:  append([]float64{}, s.means...),
		counts: append([]uint64{}, s.counts...),
	}
}