diff --git a/promql/functions.go b/promql/functions.go index e737992e46..49ff09678f 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -471,28 +471,32 @@ func funcQuantileOverTime(vals []parser.Value, args parser.Expressions, enh *Eva // === stddev_over_time(Matrix parser.ValueTypeMatrix) Vector === func funcStddevOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) Vector { return aggrOverTime(vals, enh, func(values []Point) float64 { - var aux, count, mean float64 + var count float64 + var mean, cMean float64 + var aux, cAux float64 for _, v := range values { count++ - delta := v.V - mean - mean += delta / count - aux += delta * (v.V - mean) + delta := v.V - (mean + cMean) + mean, cMean = kahanSumInc(delta/count, mean, cMean) + aux, cAux = kahanSumInc(delta*(v.V-(mean+cMean)), aux, cAux) } - return math.Sqrt(aux / count) + return math.Sqrt((aux + cAux) / count) }) } // === stdvar_over_time(Matrix parser.ValueTypeMatrix) Vector === func funcStdvarOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) Vector { return aggrOverTime(vals, enh, func(values []Point) float64 { - var aux, count, mean float64 + var count float64 + var mean, cMean float64 + var aux, cAux float64 for _, v := range values { count++ - delta := v.V - mean - mean += delta / count - aux += delta * (v.V - mean) + delta := v.V - (mean + cMean) + mean, cMean = kahanSumInc(delta/count, mean, cMean) + aux, cAux = kahanSumInc(delta*(v.V-(mean+cMean)), aux, cAux) } - return aux / count + return (aux + cAux) / count }) } diff --git a/promql/functions_test.go b/promql/functions_test.go index b0a8b5db6a..19ee105da7 100644 --- a/promql/functions_test.go +++ b/promql/functions_test.go @@ -73,8 +73,8 @@ func TestFunctionList(t *testing.T) { } } -func TestKahanSummation(t *testing.T) { +func TestKahanSum(t *testing.T) { vals := []float64{1.0, math.Pow(10, 100), 1.0, -1 * math.Pow(10, 100)} expected := 2.0 - require.Equal(t, expected, kahanSummation(vals)) + require.Equal(t, expected, kahanSum(vals)) }