Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 4c12f34

Browse files
committed
Do not include padding when hashing floating point types
The exact contents of the padding is not specified. Usually it's 0, but some optimizations in GDC sometimes lead to different padding content. For floating point types without padding, the code is unchanged. For real or imaginary types with padding, just ignore the trailing padding. For complex types where the real/imaginary types have padding, we can't hash the value as one contiguous memory block, as there will be a padding 'hole'. Here, hash real and imaginary part individually. Complex types without padding are still hashed as one memory block.
1 parent 86b0d3c commit 4c12f34

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

src/core/internal/convert.d

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ private struct Float
232232

233233
private template FloatTraits(T) if (floatFormat!T == FloatFormat.Float)
234234
{
235+
enum DATASIZE = 4;
235236
enum EXPONENT = 8;
236237
enum MANTISSA = 23;
237238
enum ZERO = Float(0, 0, 0);
@@ -244,6 +245,7 @@ private template FloatTraits(T) if (floatFormat!T == FloatFormat.Float)
244245

245246
private template FloatTraits(T) if (floatFormat!T == FloatFormat.Double)
246247
{
248+
enum DATASIZE = 8;
247249
enum EXPONENT = 11;
248250
enum MANTISSA = 52;
249251
enum ZERO = Float(0, 0, 0);
@@ -256,6 +258,7 @@ private template FloatTraits(T) if (floatFormat!T == FloatFormat.Double)
256258

257259
private template FloatTraits(T) if (floatFormat!T == FloatFormat.Real80)
258260
{
261+
enum DATASIZE = 10;
259262
enum EXPONENT = 15;
260263
enum MANTISSA = 64;
261264
enum ZERO = Float(0, 0, 0);
@@ -268,6 +271,7 @@ private template FloatTraits(T) if (floatFormat!T == FloatFormat.Real80)
268271

269272
private template FloatTraits(T) if (floatFormat!T == FloatFormat.DoubleDouble) //Unsupported in CTFE
270273
{
274+
enum DATASIZE = 16;
271275
enum EXPONENT = 11;
272276
enum MANTISSA = 106;
273277
enum ZERO = Float(0, 0, 0);
@@ -280,6 +284,7 @@ private template FloatTraits(T) if (floatFormat!T == FloatFormat.DoubleDouble) /
280284

281285
private template FloatTraits(T) if (floatFormat!T == FloatFormat.Quadruple)
282286
{
287+
enum DATASIZE = 16;
283288
enum EXPONENT = 15;
284289
enum MANTISSA = 112;
285290
enum ZERO = Float(0, 0, 0);
@@ -567,6 +572,11 @@ template floatFormat(T) if (is(T:real) || is(T:ireal))
567572

568573
}
569574

575+
package template floatSize(T) if (is(T:real) || is(T:ireal))
576+
{
577+
enum floatSize = FloatTraits!(T).DATASIZE;
578+
}
579+
570580
// all toUbyte functions must be evaluable at compile time
571581
@trusted pure nothrow @nogc
572582
const(ubyte)[] toUbyte(T)(const T[] arr) if (T.sizeof == 1)

src/core/internal/hash.d

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,8 @@ size_t hashOf(T)(scope const T val, size_t seed = 0) if (!is(T == enum) && __tra
385385
{
386386
static if (__traits(isFloating, val))
387387
{
388+
import core.internal.convert : floatSize;
389+
388390
static if (floatCoalesceZeroes || floatCoalesceNaNs)
389391
{
390392
import core.internal.traits : Unqual;
@@ -412,7 +414,23 @@ size_t hashOf(T)(scope const T val, size_t seed = 0) if (!is(T == enum) && __tra
412414
else static if (T.mant_dig == double.mant_dig && T.sizeof == ulong.sizeof)
413415
return hashOf(*cast(const ulong*) &data, seed);
414416
else
415-
return bytesHashWithExactSizeAndAlignment!T(toUbyte(data), seed);
417+
{
418+
static if (is(T : creal) && T.sizeof != 2 * floatSize!(typeof(T.re)))
419+
{
420+
auto h1 = hashOf(data.re);
421+
return hashOf(data.im, h1);
422+
}
423+
else static if (is(T : real) || is(T : ireal))
424+
{
425+
// Ignore trailing padding
426+
auto bytes = toUbyte(data)[0 .. floatSize!T];
427+
return bytesHashWithExactSizeAndAlignment!T(bytes, seed);
428+
}
429+
else
430+
{
431+
return bytesHashWithExactSizeAndAlignment!T(toUbyte(data), seed);
432+
}
433+
}
416434
}
417435
else
418436
{

0 commit comments

Comments
 (0)