Skip to content

Commit e48208b

Browse files
committed
Fix Equal and value comparison for double and float types (#3088)
(cherry picked from commit 1b5dd62)
1 parent 44b264a commit e48208b

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

src/CLR/Core/CLR_RT_HeapBlock.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,8 +1146,21 @@ CLR_UINT32 CLR_RT_HeapBlock::GetHashCode(CLR_RT_HeapBlock *ptr, bool fRecurse, C
11461146
break;
11471147

11481148
case DATATYPE_R4:
1149-
crc = (CLR_INT32)ptr->NumericByRef().u8.LL;
1149+
{
1150+
// ensure that NaN and both zeros have the same hash code
1151+
int signBit = __signbitd(ptr->NumericByRef().r4);
1152+
1153+
if (__isnanf(ptr->NumericByRef().r4) || (signBit && ptr->NumericByRef().r4 == 0))
1154+
{
1155+
crc = (CLR_INT32)(ptr->NumericByRef().u8.LL & 0x7FFFFFFF);
1156+
}
1157+
else
1158+
{
1159+
crc = (CLR_INT32)ptr->NumericByRef().u8.LL;
1160+
}
1161+
11501162
break;
1163+
}
11511164

11521165
case DATATYPE_U8:
11531166
crc = ((CLR_INT32)ptr->NumericByRef().u8.LL ^ (CLR_INT32)ptr->NumericByRef().u8.HH);
@@ -1158,8 +1171,20 @@ CLR_UINT32 CLR_RT_HeapBlock::GetHashCode(CLR_RT_HeapBlock *ptr, bool fRecurse, C
11581171
break;
11591172

11601173
case DATATYPE_R8:
1161-
crc = ((CLR_INT32)ptr->NumericByRef().r8.LL ^ (CLR_INT32)ptr->NumericByRef().r8.HH);
1174+
{
1175+
// ensure that NaN and both zeros have the same hash code
1176+
int signBit = __signbitd((double)ptr->NumericByRef().r8);
1177+
1178+
if (__isnand((double)ptr->NumericByRef().r8) || (signBit && (double)ptr->NumericByRef().r8 == 0))
1179+
{
1180+
crc = (CLR_INT32)(ptr->NumericByRef().r8.LL ^ ((CLR_INT32)ptr->NumericByRef().r8.HH & 0x7FFFFFFF));
1181+
}
1182+
else
1183+
{
1184+
crc = ((CLR_INT32)ptr->NumericByRef().r8.LL ^ (CLR_INT32)ptr->NumericByRef().r8.HH);
1185+
}
11621186
break;
1187+
}
11631188

11641189
case DATATYPE_CLASS:
11651190
case DATATYPE_VALUETYPE:

src/PAL/Include/nanoPAL_NativeDouble.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//
1+
//
22
// Copyright (c) .NET Foundation and Contributors
33
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
44
// See LICENSE file in the project root for full license information.
@@ -14,6 +14,7 @@
1414
#include <float.h>
1515

1616
#define __isnand _isnan
17+
#define __isnanf _isnan
1718
#define __isinfd(x) (!_finite(x))
1819

1920
inline int __signbitd(double x)
@@ -23,7 +24,7 @@ inline int __signbitd(double x)
2324
}
2425

2526
#define rint(x) floor((x) + 0.5)
26-
#define remainder(x, y) ((x) - ((y)*rint((x) / (y))))
27+
#define remainder(x, y) ((x) - ((y) * rint((x) / (y))))
2728

2829
#define isgreater(param0, param1) (param0 > param1)
2930
#define isless(param0, param1) (param0 < param1)

0 commit comments

Comments
 (0)