Skip to content

Commit 9b26569

Browse files
authored
util: fix codec for negative zero (#57343)
close #41878
1 parent 4fded5f commit 9b26569

File tree

4 files changed

+40
-1
lines changed

4 files changed

+40
-1
lines changed

pkg/util/codec/codec_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,3 +1333,22 @@ func TestDatumHashEquals(t *testing.T) {
13331333
require.NotEqual(t, hasher1.Sum64(), hasher2.Sum64())
13341334
require.False(t, tests[len(tests)-1].d1.Equals(tests[len(tests)-1].d2))
13351335
}
1336+
1337+
func TestEncodeFloatForNegativeZero(t *testing.T) {
1338+
floatNum := 0.0
1339+
floatNum = -floatNum
1340+
1341+
b := EncodeFloat(nil, floatNum)
1342+
_, v, err := DecodeFloat(b)
1343+
require.NoError(t, err)
1344+
require.Equal(t, floatNum, v)
1345+
require.Equal(t, math.Signbit(floatNum), math.Signbit(v))
1346+
require.Equal(t, math.Atan2(0, v), math.Pi)
1347+
1348+
b = EncodeFloatDesc(nil, floatNum)
1349+
_, v, err = DecodeFloatDesc(b)
1350+
require.NoError(t, err)
1351+
require.Equal(t, floatNum, v)
1352+
require.Equal(t, math.Signbit(floatNum), math.Signbit(v))
1353+
require.Equal(t, math.Atan2(0, v), math.Pi)
1354+
}

pkg/util/codec/float.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,17 @@ import (
2222

2323
func encodeFloatToCmpUint64(f float64) uint64 {
2424
u := math.Float64bits(f)
25-
if f >= 0 {
25+
// Check the sign bit (the highest bit in the IEEE 754 representation).
26+
// If the sign bit is 0, the number is non-negative (+0 is considered non-negative).
27+
if u&signMask == 0 {
28+
// For non-negative numbers (+0 included), set the sign bit to 1.
29+
// This ensures non-negative numbers are ordered after negative numbers
30+
// when compared as unsigned integers.
2631
u |= signMask
2732
} else {
33+
// For negative numbers (-0 included), invert all bits.
34+
// This reorders negative numbers so that the smallest (closest to 0)
35+
// has the smallest encoded value, and the most negative has the largest.
2836
u = ^u
2937
}
3038
return u

tests/integrationtest/r/expression/issues.result

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3230,3 +3230,9 @@ INSERT INTO test.t VALUES (1234567890123456);
32303230
SELECT IFNULL(id, 'abcdef') FROM test.t;
32313231
IFNULL(id, 'abcdef')
32323232
1234567890123456
3233+
DROP TABLE IF EXISTS test.t;
3234+
CREATE TABLE test.t (c0 decimal(10,0));
3235+
INSERT INTO test.t VALUES (0);
3236+
SELECT c0 FROM test.t WHERE CAST(ATAN2(((t.c0) IS NULL), (- (''))) AS TIME);
3237+
c0
3238+
0

tests/integrationtest/t/expression/issues.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,3 +2182,9 @@ DROP TABLE IF EXISTS test.t;
21822182
CREATE TABLE test.t (id bigint(11) UNSIGNED PRIMARY KEY);
21832183
INSERT INTO test.t VALUES (1234567890123456);
21842184
SELECT IFNULL(id, 'abcdef') FROM test.t;
2185+
2186+
# TestIssue41878
2187+
DROP TABLE IF EXISTS test.t;
2188+
CREATE TABLE test.t (c0 decimal(10,0));
2189+
INSERT INTO test.t VALUES (0);
2190+
SELECT c0 FROM test.t WHERE CAST(ATAN2(((t.c0) IS NULL), (- (''))) AS TIME);

0 commit comments

Comments
 (0)