diff --git a/util/kahansum/kahansum.go b/util/kahansum/kahansum.go index b9a02889b3..ea8dc6dbd4 100644 --- a/util/kahansum/kahansum.go +++ b/util/kahansum/kahansum.go @@ -15,6 +15,12 @@ package kahansum import "math" +// isInf reports whether f is positive or negative infinity. +// It avoids math.IsInf to prevent inflating Inc's inlining cost. +func isInf(f float64) bool { + return f > math.MaxFloat64 || f < -math.MaxFloat64 +} + // Inc performs addition of two floating-point numbers using the Kahan summation algorithm. func Inc(inc, sum, c float64) (newSum, newC float64) { // We've seen Kahan summation return less accurate results when Inc function is @@ -33,7 +39,7 @@ func Inc(inc, sum, c float64) (newSum, newC float64) { t := sum + inc switch { - case math.IsInf(t, 0): + case isInf(t): c = 0 // Using Neumaier improvement, swap if next term larger than sum. diff --git a/util/kahansum/kahansum_test.go b/util/kahansum/kahansum_test.go new file mode 100644 index 0000000000..b8239a4ac0 --- /dev/null +++ b/util/kahansum/kahansum_test.go @@ -0,0 +1,36 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kahansum + +import ( + "math" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestIsInf(t *testing.T) { + for _, f := range []float64{ + math.Inf(1), + math.Inf(-1), + math.MaxFloat64, + -math.MaxFloat64, + 1.0, + -1.0, + 0, + math.NaN(), + } { + require.Equal(t, math.IsInf(f, 0), isInf(f), "%e", f) + } +}