1 /*
2 * Copyright (C) 2018-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8 #pragma once
9 #include "shared/source/helpers/aligned_memory.h"
10
11 #include <cstdint>
12
13 namespace NEO {
14 // clang-format off
15 #define HASH_JENKINS_MIX(a,b,c) \
16 { \
17 a -= b; a -= c; a ^= (c>>13); \
18 b -= c; b -= a; b ^= (a<<8); \
19 c -= a; c -= b; c ^= (b>>13); \
20 a -= b; a -= c; a ^= (c>>12); \
21 b -= c; b -= a; b ^= (a<<16); \
22 c -= a; c -= b; c ^= (b>>5); \
23 a -= b; a -= c; a ^= (c>>3); \
24 b -= c; b -= a; b ^= (a<<10); \
25 c -= a; c -= b; c ^= (b>>15); \
26 }
27 // clang-format on
28 class Hash {
29 public:
Hash()30 Hash() {
31 reset();
32 };
33
getValue(const char * data,size_t size)34 uint32_t getValue(const char *data, size_t size) {
35 uint32_t value = 0;
36 switch (size) {
37 case 3:
38 value = static_cast<uint32_t>(*reinterpret_cast<const unsigned char *>(data++));
39 value <<= 8;
40 [[fallthrough]];
41 case 2:
42 value |= static_cast<uint32_t>(*reinterpret_cast<const unsigned char *>(data++));
43 value <<= 8;
44 [[fallthrough]];
45 case 1:
46 value |= static_cast<uint32_t>(*reinterpret_cast<const unsigned char *>(data++));
47 value <<= 8;
48 }
49 return value;
50 }
51
update(const char * buff,size_t size)52 void update(const char *buff, size_t size) {
53 if (buff == nullptr)
54 return;
55
56 if ((reinterpret_cast<uintptr_t>(buff) & 0x3) != 0) {
57 const unsigned char *tmp = (const unsigned char *)buff;
58
59 while (size >= sizeof(uint32_t)) {
60 uint32_t value = (uint32_t)tmp[0] + (((uint32_t)tmp[1]) << 8) + ((uint32_t)tmp[2] << 16) + ((uint32_t)tmp[3] << 24);
61 a ^= value;
62 HASH_JENKINS_MIX(a, hi, lo);
63 size -= sizeof(uint32_t);
64 tmp += sizeof(uint32_t);
65 }
66 if (size > 0) {
67 uint32_t value = getValue((char *)tmp, size);
68 a ^= value;
69 HASH_JENKINS_MIX(a, hi, lo);
70 }
71 } else {
72 const uint32_t *tmp = reinterpret_cast<const uint32_t *>(buff);
73
74 while (size >= sizeof(*tmp)) {
75 a ^= *(tmp++);
76 HASH_JENKINS_MIX(a, hi, lo);
77 size -= sizeof(*tmp);
78 }
79
80 if (size > 0) {
81 uint32_t value = getValue((char *)tmp, size);
82 a ^= value;
83 HASH_JENKINS_MIX(a, hi, lo);
84 }
85 }
86 }
87
finish()88 uint64_t finish() {
89 return (((uint64_t)hi) << 32) | lo;
90 }
91
reset()92 void reset() {
93 a = 0x428a2f98;
94 hi = 0x71374491;
95 lo = 0xb5c0fbcf;
96 }
97
hash(const char * buff,size_t size)98 static uint64_t hash(const char *buff, size_t size) {
99 Hash hash;
100 hash.update(buff, size);
101 return hash.finish();
102 }
103
104 protected:
105 uint32_t a, hi, lo;
106 };
107
108 template <typename T>
hashPtrToU32(const T * src)109 uint32_t hashPtrToU32(const T *src) {
110 auto asInt = reinterpret_cast<uintptr_t>(src);
111 constexpr auto m = sizeof(uintptr_t) / 8;
112 asInt = asInt ^ ((asInt & ~(m - 1)) >> (m * 32));
113
114 return static_cast<uint32_t>(asInt);
115 }
116 } // namespace NEO
117