mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib/decimal: properly calibrate scale for blocks with Inf values
See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/805
This commit is contained in:
parent
3e0c473cc9
commit
d448e07546
2 changed files with 25 additions and 19 deletions
|
@ -36,6 +36,9 @@ func CalibrateScale(a []int64, ae int16, b []int64, be int16) (e int16) {
|
|||
}
|
||||
upExp -= downExp
|
||||
for i, v := range a {
|
||||
if v == vInfPos || v == vInfNeg {
|
||||
continue
|
||||
}
|
||||
adjExp := upExp
|
||||
for adjExp > 0 {
|
||||
v *= 10
|
||||
|
@ -45,6 +48,9 @@ func CalibrateScale(a []int64, ae int16, b []int64, be int16) (e int16) {
|
|||
}
|
||||
if downExp > 0 {
|
||||
for i, v := range b {
|
||||
if v == vInfPos || v == vInfNeg {
|
||||
continue
|
||||
}
|
||||
adjExp := downExp
|
||||
for adjExp > 0 {
|
||||
v /= 10
|
||||
|
@ -188,9 +194,6 @@ func AppendFloatToDecimal(dst []int64, src []float64) ([]int64, int16) {
|
|||
downExp := int16(0)
|
||||
_ = ea[len(va)-1]
|
||||
for i, v := range va {
|
||||
if v == vInfPos || v == vInfNeg {
|
||||
continue
|
||||
}
|
||||
exp := ea[i]
|
||||
upExp := exp - minExp
|
||||
maxUpExp := maxUpExponent(v)
|
||||
|
@ -242,7 +245,7 @@ var vaeBufPool sync.Pool
|
|||
const int64Max = int64(1<<63 - 1)
|
||||
|
||||
func maxUpExponent(v int64) int16 {
|
||||
if v == 0 {
|
||||
if v == 0 || v == vInfPos || v == vInfNeg {
|
||||
// Any exponent allowed.
|
||||
return 1024
|
||||
}
|
||||
|
|
|
@ -131,14 +131,22 @@ func TestCalibrateScale(t *testing.T) {
|
|||
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{500, 100}, 0, 0, []int64{vInfPos, 1200}, []int64{500, 100}, 0)
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{500, 100}, 0, 2, []int64{vInfPos, 1200}, []int64{500e2, 100e2}, 0)
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{500, 100}, 0, -2, []int64{vInfPos, 1200}, []int64{5, 1}, 0)
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{3500, 100}, 0, -3, []int64{vInfPos, 1200}, []int64{3, 0}, 0)
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{35, 1}, 0, 40, []int64{0, 0}, []int64{35e17, 1e17}, 23)
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{35, 1}, 40, 0, []int64{vInfPos, 1200}, []int64{0, 0}, 40)
|
||||
testCalibrateScale(t, []int64{vInfNeg, 1200}, []int64{35, 1}, 35, -5, []int64{vInfNeg, 1200}, []int64{0, 0}, 35)
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{500, 100}, 0, -2, []int64{vInfPos, 12e4}, []int64{500, 100}, -2)
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{3500, 100}, 0, -3, []int64{vInfPos, 12e5}, []int64{3500, 100}, -3)
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{35, 1}, 0, 40, []int64{vInfPos, 0}, []int64{35e17, 1e17}, 23)
|
||||
testCalibrateScale(t, []int64{vInfPos, 1200}, []int64{35, 1}, 40, 0, []int64{vInfPos, 12e17}, []int64{0, 0}, 25)
|
||||
testCalibrateScale(t, []int64{vInfNeg, 1200}, []int64{35, 1}, 35, -5, []int64{vInfNeg, 12e17}, []int64{0, 0}, 20)
|
||||
testCalibrateScale(t, []int64{vMax, vMin, 123}, []int64{100}, 0, 3, []int64{vMax, vMin, 123}, []int64{100e3}, 0)
|
||||
testCalibrateScale(t, []int64{vMax, vMin, 123}, []int64{100}, 3, 0, []int64{vMax, vMin, 123}, []int64{0}, 3)
|
||||
testCalibrateScale(t, []int64{vMax, vMin, 123}, []int64{100}, 0, 30, []int64{92233, -92233, 0}, []int64{100e16}, 14)
|
||||
|
||||
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/805
|
||||
testCalibrateScale(t, []int64{123}, []int64{vInfPos}, 0, 0, []int64{123}, []int64{vInfPos}, 0)
|
||||
testCalibrateScale(t, []int64{123, vInfPos}, []int64{vInfNeg}, 0, 0, []int64{123, vInfPos}, []int64{vInfNeg}, 0)
|
||||
testCalibrateScale(t, []int64{123, vInfPos, vInfNeg}, []int64{456}, 0, 0, []int64{123, vInfPos, vInfNeg}, []int64{456}, 0)
|
||||
testCalibrateScale(t, []int64{123, vInfPos, vInfNeg, 456}, []int64{}, 0, 0, []int64{123, vInfPos, vInfNeg, 456}, []int64{}, 0)
|
||||
testCalibrateScale(t, []int64{123, vInfPos}, []int64{vInfNeg, 456}, 0, 0, []int64{123, vInfPos}, []int64{vInfNeg, 456}, 0)
|
||||
testCalibrateScale(t, []int64{123, vInfPos}, []int64{vInfNeg, 456}, 0, 10, []int64{123, vInfPos}, []int64{vInfNeg, 456e10}, 0)
|
||||
}
|
||||
|
||||
func testCalibrateScale(t *testing.T, a, b []int64, ae, be int16, aExpected, bExpected []int64, eExpected int16) {
|
||||
|
@ -175,7 +183,7 @@ func testCalibrateScale(t *testing.T, a, b []int64, ae, be int16, aExpected, bEx
|
|||
bCopy = append([]int64{}, b...)
|
||||
e = CalibrateScale(bCopy, be, aCopy, ae)
|
||||
if e != eExpected {
|
||||
t.Fatalf("revers: unexpected e for a=%d, b=%d, ae=%d, be=%d; got %d; expecting %d", a, b, ae, be, e, eExpected)
|
||||
t.Fatalf("reverse: unexpected e for a=%d, b=%d, ae=%d, be=%d; got %d; expecting %d", a, b, ae, be, e, eExpected)
|
||||
}
|
||||
if !reflect.DeepEqual(aCopy, aExpected) {
|
||||
t.Fatalf("reverse: unexpected a for b=%d, ae=%d, be=%d; got\n%d; expecting\n%d", b, ae, be, aCopy, aExpected)
|
||||
|
@ -193,18 +201,13 @@ func TestMaxUpExponent(t *testing.T) {
|
|||
if e != eExpected {
|
||||
t.Fatalf("unexpected e for v=%d; got %d; expecting %d", v, e, eExpected)
|
||||
}
|
||||
e = maxUpExponent(-v)
|
||||
if e != eExpected {
|
||||
t.Fatalf("unexpected e for v=%d; got %d; expecting %d", -v, e, eExpected)
|
||||
}
|
||||
}
|
||||
|
||||
f(vInfPos, 0)
|
||||
f(vInfNeg, 0)
|
||||
f(vInfPos, 1024)
|
||||
f(vInfNeg, 1024)
|
||||
f(vMin, 0)
|
||||
f(vMax, 0)
|
||||
f(0, 1024)
|
||||
f(-1<<63, 0)
|
||||
f((-1<<63)+1, 0)
|
||||
f((1<<63)-1, 0)
|
||||
f(1, 18)
|
||||
f(12, 17)
|
||||
f(123, 16)
|
||||
|
|
Loading…
Reference in a new issue