2 // Copyright (c) Microsoft. All rights reserved.
3 // This code is licensed under the MIT License (MIT).
4 // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
5 // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
6 // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
7 // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 // Developed by Minigraph
11 // Author: James Stanard
15 #include "Math/Common.h"
16 #include <smmintrin.h>
19 #define ENABLE_SSE_CRC32 1
21 #define ENABLE_SSE_CRC32 0
26 inline size_t HashRange(const uint32_t* const Begin
, const uint32_t* const End
, size_t Hash
)
29 const uint64_t* Iter64
= (const uint64_t*)Math::AlignUp(Begin
, 8);
30 const uint64_t* const End64
= (const uint64_t* const)Math::AlignDown(End
, 8);
32 // If not 64-bit aligned, start with a single u32
33 if ((uint32_t*)Iter64
> Begin
)
34 Hash
= _mm_crc32_u32((uint32_t)Hash
, *Begin
);
36 // Iterate over consecutive u64 values
37 while (Iter64
< End64
)
38 Hash
= _mm_crc32_u64((uint64_t)Hash
, *Iter64
++);
40 // If there is a 32-bit remainder, accumulate that
41 if ((uint32_t*)Iter64
< End
)
42 Hash
= _mm_crc32_u32((uint32_t)Hash
, *(uint32_t*)Iter64
);
44 // An inexpensive hash for CPUs lacking SSE4.2
45 for (const uint32_t* Iter
= Begin
; Iter
< End
; ++Iter
)
46 Hash
= 16777619U * Hash
^ *Iter
;
52 template <typename T
> inline size_t HashState( const T
* StateDesc
, size_t Count
= 1, size_t Hash
= 2166136261U )
54 static_assert((sizeof(T
) & 3) == 0 && alignof(T
) >= 4, "State object is not word-aligned");
55 return HashRange((uint32_t*)StateDesc
, (uint32_t*)(StateDesc
+ Count
), Hash
);
58 } // namespace Utility