diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bd9209 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.test +*.prof diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..339177b --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (C) 2013 Blake Mizerany + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/quantile/stream.go b/quantile/stream.go index 587b1fc..f4cabd6 100644 --- a/quantile/stream.go +++ b/quantile/stream.go @@ -133,7 +133,7 @@ if l == 0 { return 0 } - i := int(float64(l) * q) + i := int(math.Ceil(float64(l) * q)) if i > 0 { i -= 1 } diff --git a/quantile/stream_test.go b/quantile/stream_test.go index 4dba054..8551950 100644 --- a/quantile/stream_test.go +++ b/quantile/stream_test.go @@ -33,6 +33,9 @@ for quantile, epsilon := range Targets { n := float64(len(a)) k := int(quantile * n) + if k < 1 { + k = 1 + } lower := int((quantile - epsilon) * n) if lower < 1 { lower = 1 @@ -99,6 +102,30 @@ verifyPercsWithAbsoluteEpsilon(t, a, s) } +func TestTargetedQuerySmallSampleSize(t *testing.T) { + rand.Seed(42) + s := NewTargeted(TargetsSmallEpsilon) + a := []float64{1, 2, 3, 4, 5} + for _, v := range a { + s.Insert(v) + } + verifyPercsWithAbsoluteEpsilon(t, a, s) + // If not yet flushed, results should be precise: + if !s.flushed() { + for φ, want := range map[float64]float64{ + 0.01: 1, + 0.10: 1, + 0.50: 3, + 0.90: 5, + 0.99: 5, + } { + if got := s.Query(φ); got != want { + t.Errorf("want %f for φ=%f, got %f", want, φ, got) + } + } + } +} + func TestLowBiasedQuery(t *testing.T) { rand.Seed(42) s := NewLowBiased(RelativeEpsilon)