diff --git a/histogram.go b/histogram.go index 71be2af..85141d4 100644 --- a/histogram.go +++ b/histogram.go @@ -87,6 +87,10 @@ func (f *Fast) Quantile(phi float64) float64 { func (f *Fast) Quantiles(dst, phis []float64) []float64 { f.tmp = append(f.tmp[:0], f.a...) sort.Float64s(f.tmp) + return f.quantiles(dst, phis) +} + +func (f *Fast) quantiles(dst, phis []float64) []float64 { for _, phi := range phis { q := f.quantile(phi) dst = append(dst, q) @@ -129,3 +133,37 @@ func PutFast(f *Fast) { } var fastPool sync.Pool + +func Quantile(fs []*Fast, phi float64) float64 { + t := combine(fs) + return t.quantile(phi) +} + +func Quantiles(fs []*Fast, dst, phis []float64) []float64 { + t := combine(fs) + return t.quantiles(dst, phis) +} + +func combine(fs []*Fast) Fast { + n := 0 + for _, f := range fs { + n += len(f.a) + } + + var t Fast + t.Reset() + t.tmp = make([]float64, 0, n) + + for _, f := range fs { + t.tmp = append(t.tmp, f.a...) + if t.max < f.max { + t.max = f.max + } + if t.min > f.min { + t.min = f.min + } + } + sort.Float64s(t.tmp) + + return t +} diff --git a/histogram_test.go b/histogram_test.go index 9473097..9469120 100644 --- a/histogram_test.go +++ b/histogram_test.go @@ -78,3 +78,30 @@ func TestFastRepeatableResults(t *testing.T) { } } } + +func TestCombine(t *testing.T) { + f1 := GetFast() + defer PutFast(f1) + + f2 := GetFast() + defer PutFast(f2) + + for i := 0; i < 10000; i++ { + f1.Update(float64(i)) + } + for i := 10000; i < 20000; i++ { + f2.Update(float64(i)) + } + + q50 := Quantile([]*Fast{f1, f2}, 0.5) + if q50 < 9000 || q50 > 11000 { + t.Fatal(q50) + } + qs := Quantiles([]*Fast{f1, f2}, nil, []float64{0, 0.5, 1}) + if len(qs) != 3 { + t.Fatal(len(qs)) + } + if qs[0] != 0 || qs[1] != q50 || qs[2] != 19999 { + t.Fatal(qs) + } +}