be/src/exec/common/hash_table/hash.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // This file is copied from |
18 | | // https://github.com/ClickHouse/ClickHouse/blob/master/src/Common/HashTable/Hash.h |
19 | | // and modified by Doris |
20 | | |
21 | | #pragma once |
22 | | |
23 | | #include <type_traits> |
24 | | |
25 | | #include "core/extended_types.h" |
26 | | #include "core/string_ref.h" |
27 | | #include "core/types.h" |
28 | | #include "core/uint128.h" |
29 | | #include "parallel_hashmap/phmap_utils.h" |
30 | | |
31 | | // Here is an empirical value. |
32 | | static constexpr size_t HASH_MAP_PREFETCH_DIST = 16; |
33 | | |
34 | | /** Hash functions that are better than the trivial function std::hash. |
35 | | * |
36 | | * Example: when we do aggregation by the visitor ID, the performance increase is more than 5 times. |
37 | | * This is because of following reasons: |
38 | | * - in Yandex, visitor identifier is an integer that has timestamp with seconds resolution in lower bits; |
39 | | * - in typical implementation of standard library, hash function for integers is trivial and just use lower bits; |
40 | | * - traffic is non-uniformly distributed across a day; |
41 | | * - we are using open-addressing linear probing hash tables that are most critical to hash function quality, |
42 | | * and trivial hash function gives disastrous results. |
43 | | */ |
44 | | |
45 | | /** Taken from MurmurHash. This is Murmur finalizer. |
46 | | * Faster than int_hash32 when inserting into the hash table UInt64 -> UInt64, where the key is the visitor ID. |
47 | | */ |
48 | 60 | inline doris::UInt64 int_hash64(doris::UInt64 x) { |
49 | 60 | x ^= x >> 33; |
50 | 60 | x *= 0xff51afd7ed558ccdULL; |
51 | 60 | x ^= x >> 33; |
52 | 60 | x *= 0xc4ceb9fe1a85ec53ULL; |
53 | 60 | x ^= x >> 33; |
54 | | |
55 | 60 | return x; |
56 | 60 | } |
57 | | |
58 | | /** CRC32C is not very high-quality as a hash function, |
59 | | * according to avalanche and bit independence tests (see SMHasher software), as well as a small number of bits, |
60 | | * but can behave well when used in hash tables, |
61 | | * due to high speed (latency 3 + 1 clock cycle, throughput 1 clock cycle). |
62 | | * Works only with SSE 4.2 support. |
63 | | */ |
64 | | #include "util/sse_util.hpp" |
65 | | |
66 | 4.93M | inline doris::UInt64 int_hash_crc32(doris::UInt64 x) { |
67 | 4.93M | #if defined(__SSE4_2__) || (defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)) |
68 | 4.93M | return _mm_crc32_u64(-1ULL, x); |
69 | | #else |
70 | | /// On other platforms we do not have CRC32. NOTE This can be confusing. |
71 | | return int_hash64(x); |
72 | | #endif |
73 | 4.93M | } |
74 | | |
75 | | template <typename T> |
76 | 60 | inline size_t default_hash64(T key) { |
77 | 60 | union { |
78 | 60 | T in; |
79 | 60 | doris::UInt64 out; |
80 | 60 | } u; |
81 | 60 | u.out = 0; |
82 | 60 | u.in = key; |
83 | 60 | return int_hash64(u.out); |
84 | 60 | } Unexecuted instantiation: _Z14default_hash64IhEmT_ Unexecuted instantiation: _Z14default_hash64IaEmT_ Unexecuted instantiation: _Z14default_hash64IsEmT_ Line | Count | Source | 76 | 16 | inline size_t default_hash64(T key) { | 77 | 16 | union { | 78 | 16 | T in; | 79 | 16 | doris::UInt64 out; | 80 | 16 | } u; | 81 | 16 | u.out = 0; | 82 | 16 | u.in = key; | 83 | 16 | return int_hash64(u.out); | 84 | 16 | } |
Unexecuted instantiation: _Z14default_hash64IlEmT_ Line | Count | Source | 76 | 41 | inline size_t default_hash64(T key) { | 77 | 41 | union { | 78 | 41 | T in; | 79 | 41 | doris::UInt64 out; | 80 | 41 | } u; | 81 | 41 | u.out = 0; | 82 | 41 | u.in = key; | 83 | 41 | return int_hash64(u.out); | 84 | 41 | } |
Unexecuted instantiation: _Z14default_hash64IfEmT_ Line | Count | Source | 76 | 3 | inline size_t default_hash64(T key) { | 77 | 3 | union { | 78 | 3 | T in; | 79 | 3 | doris::UInt64 out; | 80 | 3 | } u; | 81 | 3 | u.out = 0; | 82 | 3 | u.in = key; | 83 | 3 | return int_hash64(u.out); | 84 | 3 | } |
Unexecuted instantiation: _Z14default_hash64IjEmT_ Unexecuted instantiation: _Z14default_hash64IoEmT_ |
85 | | |
86 | | template <typename T, typename Enable = void> |
87 | | struct DefaultHash; |
88 | | |
89 | | template <typename T> |
90 | | requires std::is_arithmetic_v<T> |
91 | | struct DefaultHash<T> { |
92 | 60 | size_t operator()(T key) const { return default_hash64<T>(key); }Unexecuted instantiation: _ZNK11DefaultHashIhvEclEh Unexecuted instantiation: _ZNK11DefaultHashIavEclEa Unexecuted instantiation: _ZNK11DefaultHashIsvEclEs _ZNK11DefaultHashIivEclEi Line | Count | Source | 92 | 16 | size_t operator()(T key) const { return default_hash64<T>(key); } |
Unexecuted instantiation: _ZNK11DefaultHashIlvEclEl _ZNK11DefaultHashInvEclEn Line | Count | Source | 92 | 41 | size_t operator()(T key) const { return default_hash64<T>(key); } |
Unexecuted instantiation: _ZNK11DefaultHashIfvEclEf _ZNK11DefaultHashIdvEclEd Line | Count | Source | 92 | 3 | size_t operator()(T key) const { return default_hash64<T>(key); } |
Unexecuted instantiation: _ZNK11DefaultHashIjvEclEj Unexecuted instantiation: _ZNK11DefaultHashIovEclEo |
93 | | }; |
94 | | |
95 | | template <> |
96 | | struct DefaultHash<doris::VecDateTimeValue> { |
97 | 0 | size_t operator()(doris::VecDateTimeValue key) const { return int_hash64(*(int64_t*)&key); } |
98 | | }; |
99 | | |
100 | | template <> |
101 | | struct DefaultHash<doris::DateV2Value<doris::DateTimeV2ValueType>> { |
102 | 0 | size_t operator()(doris::DateV2Value<doris::DateTimeV2ValueType> key) const { |
103 | 0 | return int_hash64(key.to_date_int_val()); |
104 | 0 | } |
105 | | }; |
106 | | |
107 | | template <> |
108 | | struct DefaultHash<doris::DateV2Value<doris::DateV2ValueType>> { |
109 | 0 | size_t operator()(doris::DateV2Value<doris::DateV2ValueType> key) const { |
110 | 0 | return int_hash64(key.to_date_int_val()); |
111 | 0 | } |
112 | | }; |
113 | | |
114 | | template <> |
115 | | struct DefaultHash<doris::DateTimeV2NanoValue> { |
116 | 0 | size_t operator()(doris::DateTimeV2NanoValue key) const { |
117 | 0 | return int_hash64(key.epoch_nanos()); |
118 | 0 | } |
119 | | }; |
120 | | |
121 | | template <> |
122 | | struct DefaultHash<doris::TimestampTzValue> { |
123 | 0 | size_t operator()(doris::TimestampTzValue key) const { |
124 | 0 | return int_hash64(key.to_date_int_val()); |
125 | 0 | } |
126 | | }; |
127 | | |
128 | | template <> |
129 | | struct DefaultHash<doris::StringRef> : public doris::StringRefHash {}; |
130 | | |
131 | | template <> |
132 | | struct DefaultHash<wide::Int256> : public std::hash<wide::Int256> {}; |
133 | | |
134 | | template <typename T> |
135 | | struct HashCRC32; |
136 | | |
137 | | template <typename T> |
138 | 4.93M | inline size_t hash_crc32(T key) { |
139 | 4.93M | union { |
140 | 4.93M | T in; |
141 | 4.93M | doris::UInt64 out; |
142 | 4.93M | } u; |
143 | 4.93M | u.out = 0; |
144 | 4.93M | u.in = key; |
145 | 4.93M | return int_hash_crc32(u.out); |
146 | 4.93M | } Line | Count | Source | 138 | 44.8k | inline size_t hash_crc32(T key) { | 139 | 44.8k | union { | 140 | 44.8k | T in; | 141 | 44.8k | doris::UInt64 out; | 142 | 44.8k | } u; | 143 | 44.8k | u.out = 0; | 144 | 44.8k | u.in = key; | 145 | 44.8k | return int_hash_crc32(u.out); | 146 | 44.8k | } |
Line | Count | Source | 138 | 8.50k | inline size_t hash_crc32(T key) { | 139 | 8.50k | union { | 140 | 8.50k | T in; | 141 | 8.50k | doris::UInt64 out; | 142 | 8.50k | } u; | 143 | 8.50k | u.out = 0; | 144 | 8.50k | u.in = key; | 145 | 8.50k | return int_hash_crc32(u.out); | 146 | 8.50k | } |
Line | Count | Source | 138 | 8.50k | inline size_t hash_crc32(T key) { | 139 | 8.50k | union { | 140 | 8.50k | T in; | 141 | 8.50k | doris::UInt64 out; | 142 | 8.50k | } u; | 143 | 8.50k | u.out = 0; | 144 | 8.50k | u.in = key; | 145 | 8.50k | return int_hash_crc32(u.out); | 146 | 8.50k | } |
Line | Count | Source | 138 | 7.16k | inline size_t hash_crc32(T key) { | 139 | 7.16k | union { | 140 | 7.16k | T in; | 141 | 7.16k | doris::UInt64 out; | 142 | 7.16k | } u; | 143 | 7.16k | u.out = 0; | 144 | 7.16k | u.in = key; | 145 | 7.16k | return int_hash_crc32(u.out); | 146 | 7.16k | } |
Line | Count | Source | 138 | 29.4k | inline size_t hash_crc32(T key) { | 139 | 29.4k | union { | 140 | 29.4k | T in; | 141 | 29.4k | doris::UInt64 out; | 142 | 29.4k | } u; | 143 | 29.4k | u.out = 0; | 144 | 29.4k | u.in = key; | 145 | 29.4k | return int_hash_crc32(u.out); | 146 | 29.4k | } |
Line | Count | Source | 138 | 381k | inline size_t hash_crc32(T key) { | 139 | 381k | union { | 140 | 381k | T in; | 141 | 381k | doris::UInt64 out; | 142 | 381k | } u; | 143 | 381k | u.out = 0; | 144 | 381k | u.in = key; | 145 | 381k | return int_hash_crc32(u.out); | 146 | 381k | } |
Unexecuted instantiation: _Z10hash_crc32IfEmT_ Line | Count | Source | 138 | 3 | inline size_t hash_crc32(T key) { | 139 | 3 | union { | 140 | 3 | T in; | 141 | 3 | doris::UInt64 out; | 142 | 3 | } u; | 143 | 3 | u.out = 0; | 144 | 3 | u.in = key; | 145 | 3 | return int_hash_crc32(u.out); | 146 | 3 | } |
Line | Count | Source | 138 | 4.42M | inline size_t hash_crc32(T key) { | 139 | 4.42M | union { | 140 | 4.42M | T in; | 141 | 4.42M | doris::UInt64 out; | 142 | 4.42M | } u; | 143 | 4.42M | u.out = 0; | 144 | 4.42M | u.in = key; | 145 | 4.42M | return int_hash_crc32(u.out); | 146 | 4.42M | } |
Line | Count | Source | 138 | 26.7k | inline size_t hash_crc32(T key) { | 139 | 26.7k | union { | 140 | 26.7k | T in; | 141 | 26.7k | doris::UInt64 out; | 142 | 26.7k | } u; | 143 | 26.7k | u.out = 0; | 144 | 26.7k | u.in = key; | 145 | 26.7k | return int_hash_crc32(u.out); | 146 | 26.7k | } |
|
147 | | |
148 | | template <> |
149 | 55.1k | inline size_t hash_crc32(doris::UInt128 u) { |
150 | 55.1k | return doris::UInt128HashCRC32()(u); |
151 | 55.1k | } |
152 | | |
153 | | template <> |
154 | 3 | inline size_t hash_crc32(unsigned __int128 u) { |
155 | 3 | return doris::UInt128HashCRC32()(u); |
156 | 3 | } |
157 | | |
158 | | template <> |
159 | 6 | inline size_t hash_crc32(doris::Int128 u) { |
160 | 6 | return doris::UInt128HashCRC32()({(u >> 64) & int64_t(-1), u & int64_t(-1)}); |
161 | 6 | } |
162 | | |
163 | | template <> |
164 | 0 | inline size_t hash_crc32(doris::VecDateTimeValue u) { |
165 | 0 | return hash_crc32(*(int64_t*)&u); |
166 | 0 | } |
167 | | |
168 | | template <> |
169 | 0 | inline size_t hash_crc32(doris::DateV2Value<doris::DateTimeV2ValueType> u) { |
170 | 0 | return hash_crc32(u.to_date_int_val()); |
171 | 0 | } |
172 | | |
173 | | template <> |
174 | 0 | inline size_t hash_crc32(doris::DateV2Value<doris::DateV2ValueType> u) { |
175 | 0 | return hash_crc32(u.to_date_int_val()); |
176 | 0 | } |
177 | | |
178 | | template <> |
179 | 0 | inline size_t hash_crc32(doris::DateTimeV2NanoValue u) { |
180 | 0 | return hash_crc32(u.epoch_nanos()); |
181 | 0 | } |
182 | | |
183 | | template <> |
184 | 0 | inline size_t hash_crc32(doris::TimestampTzValue u) { |
185 | 0 | return hash_crc32(u.to_date_int_val()); |
186 | 0 | } |
187 | | |
188 | | #define DEFINE_HASH(T) \ |
189 | | template <> \ |
190 | | struct HashCRC32<T> { \ |
191 | 4.98M | size_t operator()(T key) const { \ |
192 | 4.98M | return hash_crc32<T>(key); \ |
193 | 4.98M | } \ Line | Count | Source | 191 | 44.8k | size_t operator()(T key) const { \ | 192 | 44.8k | return hash_crc32<T>(key); \ | 193 | 44.8k | } \ |
Line | Count | Source | 191 | 8.50k | size_t operator()(T key) const { \ | 192 | 8.50k | return hash_crc32<T>(key); \ | 193 | 8.50k | } \ |
Line | Count | Source | 191 | 8.50k | size_t operator()(T key) const { \ | 192 | 8.50k | return hash_crc32<T>(key); \ | 193 | 8.50k | } \ |
Line | Count | Source | 191 | 7.16k | size_t operator()(T key) const { \ | 192 | 7.16k | return hash_crc32<T>(key); \ | 193 | 7.16k | } \ |
Line | Count | Source | 191 | 29.4k | size_t operator()(T key) const { \ | 192 | 29.4k | return hash_crc32<T>(key); \ | 193 | 29.4k | } \ |
Line | Count | Source | 191 | 6 | size_t operator()(T key) const { \ | 192 | 6 | return hash_crc32<T>(key); \ | 193 | 6 | } \ |
_ZNK9HashCRC32IN4wide7integerILm128EjEEEclES2_ Line | Count | Source | 191 | 55.1k | size_t operator()(T key) const { \ | 192 | 55.1k | return hash_crc32<T>(key); \ | 193 | 55.1k | } \ |
Line | Count | Source | 191 | 381k | size_t operator()(T key) const { \ | 192 | 381k | return hash_crc32<T>(key); \ | 193 | 381k | } \ |
Unexecuted instantiation: _ZNK9HashCRC32IfEclEf Line | Count | Source | 191 | 3 | size_t operator()(T key) const { \ | 192 | 3 | return hash_crc32<T>(key); \ | 193 | 3 | } \ |
Unexecuted instantiation: _ZNK9HashCRC32IN5doris11DateV2ValueINS0_15DateV2ValueTypeEEEEclES3_ Unexecuted instantiation: _ZNK9HashCRC32IN5doris11DateV2ValueINS0_19DateTimeV2ValueTypeEEEEclES3_ Unexecuted instantiation: _ZNK9HashCRC32IN5doris16TimestampTzValueEEclES1_ Line | Count | Source | 191 | 26.7k | size_t operator()(T key) const { \ | 192 | 26.7k | return hash_crc32<T>(key); \ | 193 | 26.7k | } \ |
Line | Count | Source | 191 | 4.42M | size_t operator()(T key) const { \ | 192 | 4.42M | return hash_crc32<T>(key); \ | 193 | 4.42M | } \ |
Unexecuted instantiation: _ZNK9HashCRC32IN5doris16VecDateTimeValueEEclES1_ Unexecuted instantiation: _ZNK9HashCRC32IN5doris19DateTimeV2NanoValueEEclES1_ Line | Count | Source | 191 | 3 | size_t operator()(T key) const { \ | 192 | 3 | return hash_crc32<T>(key); \ | 193 | 3 | } \ |
|
194 | | }; |
195 | | |
196 | | DEFINE_HASH(doris::UInt8) |
197 | | DEFINE_HASH(doris::UInt16) |
198 | | DEFINE_HASH(doris::UInt32) |
199 | | DEFINE_HASH(doris::UInt64) |
200 | | DEFINE_HASH(doris::UInt128) |
201 | | DEFINE_HASH(doris::Int8) |
202 | | DEFINE_HASH(doris::Int16) |
203 | | DEFINE_HASH(doris::Int32) |
204 | | DEFINE_HASH(doris::Int64) |
205 | | DEFINE_HASH(doris::Int128) |
206 | | DEFINE_HASH(doris::Float32) |
207 | | DEFINE_HASH(doris::Float64) |
208 | | DEFINE_HASH(doris::VecDateTimeValue) |
209 | | DEFINE_HASH(doris::DateV2Value<doris::DateTimeV2ValueType>) |
210 | | DEFINE_HASH(doris::DateV2Value<doris::DateV2ValueType>) |
211 | | DEFINE_HASH(doris::DateTimeV2NanoValue) |
212 | | DEFINE_HASH(doris::TimestampTzValue) |
213 | | DEFINE_HASH(unsigned __int128) |
214 | | |
215 | | #undef DEFINE_HASH |
216 | | |
217 | | template <typename Key, typename Hash = HashCRC32<Key>> |
218 | | struct HashMixWrapper { |
219 | 4.67M | size_t operator()(Key key) const { return phmap::phmap_mix<sizeof(size_t)>()(Hash()(key)); }_ZNK14HashMixWrapperIm9HashCRC32ImEEclEm Line | Count | Source | 219 | 348k | size_t operator()(Key key) const { return phmap::phmap_mix<sizeof(size_t)>()(Hash()(key)); } |
_ZNK14HashMixWrapperIj9HashCRC32IjEEclEj Line | Count | Source | 219 | 4.32M | size_t operator()(Key key) const { return phmap::phmap_mix<sizeof(size_t)>()(Hash()(key)); } |
|
220 | | }; |
221 | | |
222 | | template <> |
223 | | struct HashCRC32<doris::UInt256> { |
224 | 24 | size_t operator()(const doris::UInt256& x) const { |
225 | 24 | #if defined(__SSE4_2__) || defined(__aarch64__) |
226 | 24 | doris::UInt64 crc = -1ULL; |
227 | 24 | crc = _mm_crc32_u64(crc, x.items[0]); |
228 | 24 | crc = _mm_crc32_u64(crc, x.items[1]); |
229 | 24 | crc = _mm_crc32_u64(crc, x.items[2]); |
230 | 24 | crc = _mm_crc32_u64(crc, x.items[3]); |
231 | 24 | return crc; |
232 | | #else |
233 | | return Hash128to64({Hash128to64({x.a, x.b}), Hash128to64({x.c, x.d})}); |
234 | | #endif |
235 | 24 | } |
236 | | }; |
237 | | |
238 | | template <> |
239 | | struct HashCRC32<wide::Int256> { |
240 | 8.19k | size_t operator()(const wide::Int256& x) const { |
241 | 8.19k | #if defined(__SSE4_2__) || defined(__aarch64__) |
242 | 8.19k | doris::UInt64 crc = -1ULL; |
243 | 8.19k | crc = _mm_crc32_u64(crc, x.items[0]); |
244 | 8.19k | crc = _mm_crc32_u64(crc, x.items[1]); |
245 | 8.19k | crc = _mm_crc32_u64(crc, x.items[2]); |
246 | 8.19k | crc = _mm_crc32_u64(crc, x.items[3]); |
247 | 8.19k | return crc; |
248 | | #else |
249 | | return Hash128to64( |
250 | | {Hash128to64({x.items[0], x.items[1]}), Hash128to64({x.items[2], x.items[3]})}); |
251 | | #endif |
252 | 8.19k | } |
253 | | }; |
254 | | |
255 | | template <> |
256 | | struct HashCRC32<doris::Decimal256> { |
257 | 0 | size_t operator()(const doris::Decimal256& value) const { |
258 | 0 | return HashCRC32<wide::Int256>()(value.value); |
259 | 0 | } |
260 | | }; |
261 | | |
262 | | template <> |
263 | | struct HashCRC32<doris::Decimal32> { |
264 | 0 | size_t operator()(const doris::Decimal32& value) const { |
265 | 0 | return HashCRC32<int32_t>()(value.value); |
266 | 0 | } |
267 | | }; |
268 | | |
269 | | template <> |
270 | | struct HashCRC32<doris::Decimal64> { |
271 | 0 | size_t operator()(const doris::Decimal64& value) const { |
272 | 0 | return HashCRC32<int64_t>()(value.value); |
273 | 0 | } |
274 | | }; |
275 | | |
276 | | template <> |
277 | | struct HashCRC32<doris::Decimal128V3> { |
278 | 0 | size_t operator()(const doris::Decimal128V3& value) const { |
279 | 0 | return HashCRC32<__int128>()(value.value); |
280 | 0 | } |
281 | | }; |
282 | | |
283 | | template <> |
284 | | struct HashCRC32<doris::Decimal128V2> { |
285 | 0 | size_t operator()(const doris::Decimal128V2& value) const { |
286 | 0 | return HashCRC32<__int128>()(value.value); |
287 | 0 | } |
288 | | }; |
289 | | |
290 | | template <> |
291 | | struct HashCRC32<doris::DecimalV2Value> { |
292 | 0 | size_t operator()(const doris::DecimalV2Value& value) const { |
293 | 0 | return HashCRC32<__int128>()(value.value()); |
294 | 0 | } |
295 | | }; |
296 | | |
297 | | #include "common/compile_check_avoid_begin.h" |
298 | | |
299 | | template <> |
300 | | struct HashCRC32<doris::UInt72> { |
301 | 66 | size_t operator()(const doris::UInt72& x) const { |
302 | 66 | doris::UInt64 crc = -1ULL; |
303 | 66 | crc = _mm_crc32_u8(crc, x.a); |
304 | 66 | crc = _mm_crc32_u64(crc, x.b); |
305 | 66 | return crc; |
306 | 66 | } |
307 | | }; |
308 | | |
309 | | template <> |
310 | | struct HashCRC32<doris::UInt96> { |
311 | 21 | size_t operator()(const doris::UInt96& x) const { |
312 | 21 | doris::UInt64 crc = -1ULL; |
313 | 21 | crc = _mm_crc32_u32(crc, x.a); |
314 | 21 | crc = _mm_crc32_u64(crc, x.b); |
315 | 21 | return crc; |
316 | 21 | } |
317 | | }; |
318 | | |
319 | | template <> |
320 | | struct HashCRC32<doris::UInt104> { |
321 | 54 | size_t operator()(const doris::UInt104& x) const { |
322 | 54 | doris::UInt64 crc = -1ULL; |
323 | 54 | crc = _mm_crc32_u8(crc, x.a); |
324 | 54 | crc = _mm_crc32_u32(crc, x.b); |
325 | 54 | crc = _mm_crc32_u64(crc, x.c); |
326 | 54 | return crc; |
327 | 54 | } |
328 | | }; |
329 | | |
330 | | template <> |
331 | | struct HashCRC32<doris::UInt136> { |
332 | 2 | size_t operator()(const doris::UInt136& x) const { |
333 | 2 | doris::UInt64 crc = -1ULL; |
334 | 2 | crc = _mm_crc32_u8(crc, x.a); |
335 | 2 | crc = _mm_crc32_u64(crc, x.b); |
336 | 2 | crc = _mm_crc32_u64(crc, x.c); |
337 | 2 | return crc; |
338 | 2 | } |
339 | | }; |
340 | | |
341 | | #include "common/compile_check_avoid_end.h" |