@@ -623,14 +623,16 @@ size_t bytesHash()(scope const(void)* buf, size_t len, size_t seed)
623623
624624private template bytesHashAlignedBy (AlignType)
625625{
626- alias bytesHashAlignedBy = bytesHash! (AlignType.alignof >= uint .alignof);
626+ static if (size_t .sizeof == 4 )
627+ alias bytesHashAlignedBy = bytesHash32! (AlignType.alignof >= uint .alignof);
628+ else
629+ alias bytesHashAlignedBy = bytesHash64! ();
627630}
628631
629632private template bytesHashWithExactSizeAndAlignment (SizeAndAlignType)
630633{
631- static if (SizeAndAlignType.alignof < uint .alignof
632- ? SizeAndAlignType.sizeof <= 12
633- : SizeAndAlignType.sizeof <= 10 )
634+ static if (SizeAndAlignType.sizeof <= 3 || size_t .sizeof <= 4 &&
635+ SizeAndAlignType.sizeof <= (SizeAndAlignType.alignof < uint .alignof ? 12 : 10 ))
634636 alias bytesHashWithExactSizeAndAlignment = smallBytesHash;
635637 else
636638 alias bytesHashWithExactSizeAndAlignment = bytesHashAlignedBy! SizeAndAlignType;
@@ -670,8 +672,9 @@ private uint get32bits()(scope const(ubyte)* x) @nogc nothrow pure @system
670672Params:
671673 dataKnownToBeAligned = whether the data is known at compile time to be uint-aligned.
672674+/
675+ static if (size_t .sizeof == 4 )
673676@nogc nothrow pure @trusted
674- private size_t bytesHash (bool dataKnownToBeAligned)(scope const (ubyte )[] bytes, size_t seed)
677+ private uint bytesHash32 (bool dataKnownToBeAligned)(scope const (ubyte )[] bytes, size_t seed)
675678{
676679 auto len = bytes.length;
677680 auto data = bytes.ptr;
@@ -725,6 +728,84 @@ private size_t bytesHash(bool dataKnownToBeAligned)(scope const(ubyte)[] bytes,
725728 return h1;
726729}
727730
731+ static if (size_t .sizeof == 8 )
732+ @nogc nothrow pure @trusted
733+ private ulong bytesHash64 ()(scope const ubyte [] bytes, ulong seed)
734+ {
735+ alias h1 = seed;
736+
737+ enum ulong c1 = 0x87c37b91114253d5 ;
738+ enum ulong c2 = 0x4cf5ad432745937f ;
739+ enum uint c3 = 0x52dce729 ;
740+
741+ const (ubyte )* data = bytes.ptr;
742+ // ----------
743+ // body
744+ for (const end_data = bytes.ptr + (bytes.length & ~ 7 );
745+ data ! is end_data;
746+ data += 8 )
747+ {
748+ version (BigEndian )
749+ {
750+ auto k1 =
751+ ((cast (ulong ) data[0 ]) << 56 ) |
752+ ((cast (ulong ) data[1 ]) << 48 ) |
753+ ((cast (ulong ) data[2 ]) << 40 ) |
754+ ((cast (ulong ) data[3 ]) << 32 ) |
755+ ((cast (ulong ) data[4 ]) << 24 ) |
756+ ((cast (ulong ) data[5 ]) << 16 ) |
757+ ((cast (ulong ) data[6 ]) << 8 ) |
758+ (cast (ulong ) data[7 ]);
759+ }
760+ else
761+ {
762+ auto k1 =
763+ ((cast (ulong ) data[7 ]) << 56 ) |
764+ ((cast (ulong ) data[6 ]) << 48 ) |
765+ ((cast (ulong ) data[5 ]) << 40 ) |
766+ ((cast (ulong ) data[4 ]) << 32 ) |
767+ ((cast (ulong ) data[3 ]) << 24 ) |
768+ ((cast (ulong ) data[2 ]) << 16 ) |
769+ ((cast (ulong ) data[1 ]) << 8 ) |
770+ (cast (ulong ) data[0 ]);
771+ }
772+
773+ k1 *= c1;
774+ k1 = (k1 << 31 ) | (k1 >> (64 - 31 ));
775+ k1 *= c2;
776+
777+ h1 ^= k1;
778+ h1 = (h1 << 27 ) | (h1 >> (64 - 27 ));
779+ h1 = h1* 5 + c3;
780+ }
781+
782+ // ----------
783+ // tail
784+ ulong k1 = 0 ;
785+
786+ switch (bytes.length & 7 )
787+ {
788+ case 7 : k1 ^= (cast (ulong ) data[6 ]) << 48 ; goto case ;
789+ case 6 : k1 ^= (cast (ulong ) data[5 ]) << 40 ; goto case ;
790+ case 5 : k1 ^= (cast (ulong ) data[4 ]) << 32 ; goto case ;
791+ case 4 : k1 ^= (cast (ulong ) data[3 ]) << 24 ; goto case ;
792+ case 3 : k1 ^= (cast (ulong ) data[2 ]) << 16 ; goto case ;
793+ case 2 : k1 ^= (cast (ulong ) data[1 ]) << 8 ; goto case ;
794+ case 1 : k1 ^= (cast (ulong ) data[0 ]);
795+ k1 *= c1; k1 = (k1 << 31 ) | (k1 >> (64 - 31 )); k1 *= c2; h1 ^= k1;
796+ goto default ;
797+ default :
798+ }
799+
800+ // ----------
801+ // finalization
802+ h1 ^= bytes.length;
803+ // Force all bits of the hash block to avalanche.
804+ h1 = (h1 ^ (h1 >> 33 )) * 0xff51afd7ed558ccd ;
805+ h1 = (h1 ^ (h1 >> 33 )) * 0xc4ceb9fe1a85ec53 ;
806+ return h1 ^= h1 >> 33 ;
807+ }
808+
728809// Check that bytesHash works with CTFE
729810pure nothrow @system @nogc unittest
730811{
@@ -750,7 +831,8 @@ pure nothrow @system @nogc unittest
750831 }
751832 // It is okay to change the below values if you make a change
752833 // that you expect to change the result of bytesHash.
753- assert (bytesHash(&a[1 ], a.length - 2 , 0 ) == 2727459272 );
754- assert (bytesHash(&b, 5 , 0 ) == 2727459272 );
755- assert (bytesHashAlignedBy! uint ((cast (const ubyte * ) &b)[0 .. 5 ], 0 ) == 2727459272 );
834+ enum expectedResult = size_t .sizeof == 4 ? 2727459272U : 10677742034643552556UL ;
835+ assert (bytesHash(&a[1 ], a.length - 2 , 0 ) == expectedResult);
836+ assert (bytesHash(&b, 5 , 0 ) == expectedResult);
837+ assert (bytesHashAlignedBy! uint ((cast (const ubyte * ) &b)[0 .. 5 ], 0 ) == expectedResult);
756838}
0 commit comments