stat: explicitly panic when calling Quantile with empty x
MODIFY
stat/stat.go
stat/stat.go
@@ -1026,6 +1026,7 @@ func MomentAbout(moment float64, x []float64, mean float64, weights []float64) f
//
// The x data must be sorted in increasing order. If weights is nil then all
// of the weights are 1. If weights is not nil, then len(x) must equal len(weights).
+// Quantile will panic if the length of x is zero.
//
// CumulantKind behaviors:
// - Empirical: Returns the lowest value q for which q is greater than or equal
@@ -1039,6 +1040,9 @@ func Quantile(p float64, c CumulantKind, x, weights []float64) float64 {
if weights != nil && len(x) != len(weights) {
panic("stat: slice length mismatch")
}
+ if len(x) == 0 {
+ panic("stat: zero length slice")
+ }
if floats.HasNaN(x) {
return math.NaN() // This is needed because the algorithm breaks otherwise.
}

MODIFY
stat/stat_test.go
stat/stat_test.go
@@ -1433,7 +1433,29 @@ func TestQuantile(t *testing.T) {
x []float64
w []float64
ans [][]float64
+ panics bool
}{
+ {
+ p: []float64{0, 0.05, 0.1, 0.15, 0.45, 0.5, 0.55, 0.85, 0.9, 0.95, 1},
+ x: nil,
+ w: nil,
+ panics: true,
+ },
+ {
+ p: []float64{0, 0.05, 0.1, 0.15, 0.45, 0.5, 0.55, 0.85, 0.9, 0.95, 1},
+ x: []float64{},
+ w: nil,
+ panics: true,
+ },
+ {
+ p: []float64{0, 0.05, 0.1, 0.15, 0.45, 0.5, 0.55, 0.85, 0.9, 0.95, 1},
+ x: []float64{1},
+ w: nil,
+ ans: [][]float64{
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ },
+ },
{
p: []float64{0, 0.05, 0.1, 0.15, 0.45, 0.5, 0.55, 0.85, 0.9, 0.95, 1},
x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
@@ -1479,13 +1501,19 @@ func TestQuantile(t *testing.T) {
}
for j, p := range test.p {
for k, kind := range cumulantKinds {
- v := Quantile(p, kind, test.x, test.w)
+ var v float64
+ if test.panics != panics(func() { v = Quantile(p, kind, test.x, test.w) }) {
+ t.Errorf("Quantile did not panic when expected: test %d", j)
+ }
if !floats.Same(copyX, test.x) {
t.Errorf("x changed for case %d kind %d percentile %v", i, k, p)
}
if !floats.Same(copyW, test.w) {
t.Errorf("x changed for case %d kind %d percentile %v", i, k, p)
}
+ if test.panics {
+ continue
+ }
if v != test.ans[k][j] && !(math.IsNaN(v) && math.IsNaN(test.ans[k][j])) {
t.Errorf("mismatch case %d kind %d percentile %v. Expected: %v, found: %v", i, k, p, test.ans[k][j], v)
}

stat: explicitly panic when calling Quantile with empty x