Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions pkg/util/codec/codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1333,3 +1333,22 @@ func TestDatumHashEquals(t *testing.T) {
require.NotEqual(t, hasher1.Sum64(), hasher2.Sum64())
require.False(t, tests[len(tests)-1].d1.Equals(tests[len(tests)-1].d2))
}

func TestEncodeFloatForNegativeZero(t *testing.T) {
floatNum := 0.0
floatNum = -floatNum

b := EncodeFloat(nil, floatNum)
_, v, err := DecodeFloat(b)
require.NoError(t, err)
require.Equal(t, floatNum, v)
require.Equal(t, math.Signbit(floatNum), math.Signbit(v))
require.Equal(t, math.Atan2(0, v), math.Pi)

b = EncodeFloatDesc(nil, floatNum)
_, v, err = DecodeFloatDesc(b)
require.NoError(t, err)
require.Equal(t, floatNum, v)
require.Equal(t, math.Signbit(floatNum), math.Signbit(v))
require.Equal(t, math.Atan2(0, v), math.Pi)
}
10 changes: 9 additions & 1 deletion pkg/util/codec/float.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,17 @@ import (

func encodeFloatToCmpUint64(f float64) uint64 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some comments to make it more readable

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

u := math.Float64bits(f)
if f >= 0 {
// Check the sign bit (the highest bit in the IEEE 754 representation).
// If the sign bit is 0, the number is non-negative (+0 is considered non-negative).
if u&signMask == 0 {
// For non-negative numbers (+0 included), set the sign bit to 1.
// This ensures non-negative numbers are ordered after negative numbers
// when compared as unsigned integers.
u |= signMask
} else {
// For negative numbers (-0 included), invert all bits.
// This reorders negative numbers so that the smallest (closest to 0)
// has the smallest encoded value, and the most negative has the largest.
u = ^u
}
return u
Expand Down
6 changes: 6 additions & 0 deletions tests/integrationtest/r/expression/issues.result
Original file line number Diff line number Diff line change
Expand Up @@ -3230,3 +3230,9 @@ INSERT INTO test.t VALUES (1234567890123456);
SELECT IFNULL(id, 'abcdef') FROM test.t;
IFNULL(id, 'abcdef')
1234567890123456
DROP TABLE IF EXISTS test.t;
CREATE TABLE test.t (c0 decimal(10,0));
INSERT INTO test.t VALUES (0);
SELECT c0 FROM test.t WHERE CAST(ATAN2(((t.c0) IS NULL), (- (''))) AS TIME);
c0
0
6 changes: 6 additions & 0 deletions tests/integrationtest/t/expression/issues.test
Original file line number Diff line number Diff line change
Expand Up @@ -2182,3 +2182,9 @@ DROP TABLE IF EXISTS test.t;
CREATE TABLE test.t (id bigint(11) UNSIGNED PRIMARY KEY);
INSERT INTO test.t VALUES (1234567890123456);
SELECT IFNULL(id, 'abcdef') FROM test.t;

# TestIssue41878
DROP TABLE IF EXISTS test.t;
CREATE TABLE test.t (c0 decimal(10,0));
INSERT INTO test.t VALUES (0);
SELECT c0 FROM test.t WHERE CAST(ATAN2(((t.c0) IS NULL), (- (''))) AS TIME);