Coverage Report

Created: 2026-10-19 22:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
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 "core/value/timestamp_ns_value.h"
30
#include "parallel_hashmap/phmap_utils.h"
31
32
// Here is an empirical value.
33
static constexpr size_t HASH_MAP_PREFETCH_DIST = 16;
34
35
/** Hash functions that are better than the trivial function std::hash.
36
  *
37
  * Example: when we do aggregation by the visitor ID, the performance increase is more than 5 times.
38
  * This is because of following reasons:
39
  * - in Yandex, visitor identifier is an integer that has timestamp with seconds resolution in lower bits;
40
  * - in typical implementation of standard library, hash function for integers is trivial and just use lower bits;
41
  * - traffic is non-uniformly distributed across a day;
42
  * - we are using open-addressing linear probing hash tables that are most critical to hash function quality,
43
  *   and trivial hash function gives disastrous results.
44
  */
45
46
/** Taken from MurmurHash. This is Murmur finalizer.
47
  * Faster than int_hash32 when inserting into the hash table UInt64 -> UInt64, where the key is the visitor ID.
48
  */
49
15.8k
inline doris::UInt64 int_hash64(doris::UInt64 x) {
50
15.8k
    x ^= x >> 33;
51
15.8k
    x *= 0xff51afd7ed558ccdULL;
52
15.8k
    x ^= x >> 33;
53
15.8k
    x *= 0xc4ceb9fe1a85ec53ULL;
54
15.8k
    x ^= x >> 33;
55
56
15.8k
    return x;
57
15.8k
}
58
59
/** CRC32C is not very high-quality as a hash function,
60
  *  according to avalanche and bit independence tests (see SMHasher software), as well as a small number of bits,
61
  *  but can behave well when used in hash tables,
62
  *  due to high speed (latency 3 + 1 clock cycle, throughput 1 clock cycle).
63
  * Works only with SSE 4.2 support.
64
  */
65
#include "util/sse_util.hpp"
66
67
23.3M
inline doris::UInt64 int_hash_crc32(doris::UInt64 x) {
68
23.3M
#if defined(__SSE4_2__) || (defined(__aarch64__) && defined(__ARM_FEATURE_CRC32))
69
23.3M
    return _mm_crc32_u64(-1ULL, x);
70
#else
71
    /// On other platforms we do not have CRC32. NOTE This can be confusing.
72
    return int_hash64(x);
73
#endif
74
23.3M
}
75
76
template <typename T>
77
13.4k
inline size_t default_hash64(T key) {
78
13.4k
    union {
79
13.4k
        T in;
80
13.4k
        doris::UInt64 out;
81
13.4k
    } u;
82
13.4k
    u.out = 0;
83
13.4k
    u.in = key;
84
13.4k
    return int_hash64(u.out);
85
13.4k
}
_Z14default_hash64IhEmT_
Line
Count
Source
77
112
inline size_t default_hash64(T key) {
78
112
    union {
79
112
        T in;
80
112
        doris::UInt64 out;
81
112
    } u;
82
112
    u.out = 0;
83
112
    u.in = key;
84
112
    return int_hash64(u.out);
85
112
}
_Z14default_hash64IaEmT_
Line
Count
Source
77
869
inline size_t default_hash64(T key) {
78
869
    union {
79
869
        T in;
80
869
        doris::UInt64 out;
81
869
    } u;
82
869
    u.out = 0;
83
869
    u.in = key;
84
869
    return int_hash64(u.out);
85
869
}
_Z14default_hash64IsEmT_
Line
Count
Source
77
1.56k
inline size_t default_hash64(T key) {
78
1.56k
    union {
79
1.56k
        T in;
80
1.56k
        doris::UInt64 out;
81
1.56k
    } u;
82
1.56k
    u.out = 0;
83
1.56k
    u.in = key;
84
1.56k
    return int_hash64(u.out);
85
1.56k
}
_Z14default_hash64IiEmT_
Line
Count
Source
77
3.56k
inline size_t default_hash64(T key) {
78
3.56k
    union {
79
3.56k
        T in;
80
3.56k
        doris::UInt64 out;
81
3.56k
    } u;
82
3.56k
    u.out = 0;
83
3.56k
    u.in = key;
84
3.56k
    return int_hash64(u.out);
85
3.56k
}
_Z14default_hash64IlEmT_
Line
Count
Source
77
1.42k
inline size_t default_hash64(T key) {
78
1.42k
    union {
79
1.42k
        T in;
80
1.42k
        doris::UInt64 out;
81
1.42k
    } u;
82
1.42k
    u.out = 0;
83
1.42k
    u.in = key;
84
1.42k
    return int_hash64(u.out);
85
1.42k
}
_Z14default_hash64InEmT_
Line
Count
Source
77
3.63k
inline size_t default_hash64(T key) {
78
3.63k
    union {
79
3.63k
        T in;
80
3.63k
        doris::UInt64 out;
81
3.63k
    } u;
82
3.63k
    u.out = 0;
83
3.63k
    u.in = key;
84
3.63k
    return int_hash64(u.out);
85
3.63k
}
_Z14default_hash64IfEmT_
Line
Count
Source
77
630
inline size_t default_hash64(T key) {
78
630
    union {
79
630
        T in;
80
630
        doris::UInt64 out;
81
630
    } u;
82
630
    u.out = 0;
83
630
    u.in = key;
84
630
    return int_hash64(u.out);
85
630
}
_Z14default_hash64IdEmT_
Line
Count
Source
77
805
inline size_t default_hash64(T key) {
78
805
    union {
79
805
        T in;
80
805
        doris::UInt64 out;
81
805
    } u;
82
805
    u.out = 0;
83
805
    u.in = key;
84
805
    return int_hash64(u.out);
85
805
}
_Z14default_hash64IjEmT_
Line
Count
Source
77
876
inline size_t default_hash64(T key) {
78
876
    union {
79
876
        T in;
80
876
        doris::UInt64 out;
81
876
    } u;
82
876
    u.out = 0;
83
876
    u.in = key;
84
876
    return int_hash64(u.out);
85
876
}
86
87
template <typename T, typename Enable = void>
88
struct DefaultHash;
89
90
template <typename T>
91
    requires std::is_arithmetic_v<T>
92
struct DefaultHash<T> {
93
13.4k
    size_t operator()(T key) const { return default_hash64<T>(key); }
_ZNK11DefaultHashIhvEclEh
Line
Count
Source
93
112
    size_t operator()(T key) const { return default_hash64<T>(key); }
_ZNK11DefaultHashIavEclEa
Line
Count
Source
93
869
    size_t operator()(T key) const { return default_hash64<T>(key); }
_ZNK11DefaultHashIsvEclEs
Line
Count
Source
93
1.56k
    size_t operator()(T key) const { return default_hash64<T>(key); }
_ZNK11DefaultHashIivEclEi
Line
Count
Source
93
3.56k
    size_t operator()(T key) const { return default_hash64<T>(key); }
_ZNK11DefaultHashIlvEclEl
Line
Count
Source
93
1.42k
    size_t operator()(T key) const { return default_hash64<T>(key); }
_ZNK11DefaultHashInvEclEn
Line
Count
Source
93
3.63k
    size_t operator()(T key) const { return default_hash64<T>(key); }
_ZNK11DefaultHashIfvEclEf
Line
Count
Source
93
630
    size_t operator()(T key) const { return default_hash64<T>(key); }
_ZNK11DefaultHashIdvEclEd
Line
Count
Source
93
805
    size_t operator()(T key) const { return default_hash64<T>(key); }
_ZNK11DefaultHashIjvEclEj
Line
Count
Source
93
876
    size_t operator()(T key) const { return default_hash64<T>(key); }
94
};
95
96
template <>
97
struct DefaultHash<unsigned __int128> {
98
436k
    size_t operator()(unsigned __int128 key) const { return doris::UInt128HashCRC32()(key); }
99
};
100
101
template <>
102
struct DefaultHash<doris::VecDateTimeValue> {
103
0
    size_t operator()(doris::VecDateTimeValue key) const { return int_hash64(*(int64_t*)&key); }
104
};
105
106
template <>
107
struct DefaultHash<doris::DateV2Value<doris::DateTimeV2ValueType>> {
108
531
    size_t operator()(doris::DateV2Value<doris::DateTimeV2ValueType> key) const {
109
531
        return int_hash64(key.to_date_int_val());
110
531
    }
111
};
112
113
template <>
114
struct DefaultHash<doris::DateV2Value<doris::DateV2ValueType>> {
115
1.62k
    size_t operator()(doris::DateV2Value<doris::DateV2ValueType> key) const {
116
1.62k
        return int_hash64(key.to_date_int_val());
117
1.62k
    }
118
};
119
120
template <>
121
struct DefaultHash<doris::TimeStampNsValue> {
122
224
    size_t operator()(doris::TimeStampNsValue key) const { return int_hash64(key.epoch_nanos()); }
123
};
124
125
template <>
126
struct DefaultHash<doris::TimestampTzValue> {
127
0
    size_t operator()(doris::TimestampTzValue key) const {
128
0
        return int_hash64(key.to_date_int_val());
129
0
    }
130
};
131
132
template <>
133
struct DefaultHash<doris::StringRef> : public doris::StringRefHash {};
134
135
template <>
136
struct DefaultHash<wide::Int256> : public std::hash<wide::Int256> {};
137
138
template <typename T>
139
struct HashCRC32;
140
141
template <typename T>
142
23.3M
inline size_t hash_crc32(T key) {
143
23.3M
    union {
144
23.3M
        T in;
145
23.3M
        doris::UInt64 out;
146
23.3M
    } u;
147
23.3M
    u.out = 0;
148
23.3M
    u.in = key;
149
23.3M
    return int_hash_crc32(u.out);
150
23.3M
}
_Z10hash_crc32IlEmT_
Line
Count
Source
142
248k
inline size_t hash_crc32(T key) {
143
248k
    union {
144
248k
        T in;
145
248k
        doris::UInt64 out;
146
248k
    } u;
147
248k
    u.out = 0;
148
248k
    u.in = key;
149
248k
    return int_hash_crc32(u.out);
150
248k
}
_Z10hash_crc32ImEmT_
Line
Count
Source
142
5.82M
inline size_t hash_crc32(T key) {
143
5.82M
    union {
144
5.82M
        T in;
145
5.82M
        doris::UInt64 out;
146
5.82M
    } u;
147
5.82M
    u.out = 0;
148
5.82M
    u.in = key;
149
5.82M
    return int_hash_crc32(u.out);
150
5.82M
}
_Z10hash_crc32IjEmT_
Line
Count
Source
142
16.5M
inline size_t hash_crc32(T key) {
143
16.5M
    union {
144
16.5M
        T in;
145
16.5M
        doris::UInt64 out;
146
16.5M
    } u;
147
16.5M
    u.out = 0;
148
16.5M
    u.in = key;
149
16.5M
    return int_hash_crc32(u.out);
150
16.5M
}
_Z10hash_crc32IhEmT_
Line
Count
Source
142
451k
inline size_t hash_crc32(T key) {
143
451k
    union {
144
451k
        T in;
145
451k
        doris::UInt64 out;
146
451k
    } u;
147
451k
    u.out = 0;
148
451k
    u.in = key;
149
451k
    return int_hash_crc32(u.out);
150
451k
}
_Z10hash_crc32ItEmT_
Line
Count
Source
142
21.1k
inline size_t hash_crc32(T key) {
143
21.1k
    union {
144
21.1k
        T in;
145
21.1k
        doris::UInt64 out;
146
21.1k
    } u;
147
21.1k
    u.out = 0;
148
21.1k
    u.in = key;
149
21.1k
    return int_hash_crc32(u.out);
150
21.1k
}
_Z10hash_crc32IaEmT_
Line
Count
Source
142
8.92k
inline size_t hash_crc32(T key) {
143
8.92k
    union {
144
8.92k
        T in;
145
8.92k
        doris::UInt64 out;
146
8.92k
    } u;
147
8.92k
    u.out = 0;
148
8.92k
    u.in = key;
149
8.92k
    return int_hash_crc32(u.out);
150
8.92k
}
_Z10hash_crc32IsEmT_
Line
Count
Source
142
8.50k
inline size_t hash_crc32(T key) {
143
8.50k
    union {
144
8.50k
        T in;
145
8.50k
        doris::UInt64 out;
146
8.50k
    } u;
147
8.50k
    u.out = 0;
148
8.50k
    u.in = key;
149
8.50k
    return int_hash_crc32(u.out);
150
8.50k
}
_Z10hash_crc32IiEmT_
Line
Count
Source
142
202k
inline size_t hash_crc32(T key) {
143
202k
    union {
144
202k
        T in;
145
202k
        doris::UInt64 out;
146
202k
    } u;
147
202k
    u.out = 0;
148
202k
    u.in = key;
149
202k
    return int_hash_crc32(u.out);
150
202k
}
Unexecuted instantiation: _Z10hash_crc32IfEmT_
_Z10hash_crc32IdEmT_
Line
Count
Source
142
5
inline size_t hash_crc32(T key) {
143
5
    union {
144
5
        T in;
145
5
        doris::UInt64 out;
146
5
    } u;
147
5
    u.out = 0;
148
5
    u.in = key;
149
5
    return int_hash_crc32(u.out);
150
5
}
151
152
template <>
153
3.48M
inline size_t hash_crc32(doris::UInt128 u) {
154
3.48M
    return doris::UInt128HashCRC32()(u);
155
3.48M
}
156
157
template <>
158
34
inline size_t hash_crc32(unsigned __int128 u) {
159
34
    return doris::UInt128HashCRC32()(u);
160
34
}
161
162
template <>
163
264
inline size_t hash_crc32(doris::Int128 u) {
164
264
    return doris::UInt128HashCRC32()({(u >> 64) & int64_t(-1), u & int64_t(-1)});
165
264
}
166
167
template <>
168
0
inline size_t hash_crc32(doris::VecDateTimeValue u) {
169
0
    return hash_crc32(*(int64_t*)&u);
170
0
}
171
172
template <>
173
40
inline size_t hash_crc32(doris::DateV2Value<doris::DateTimeV2ValueType> u) {
174
40
    return hash_crc32(u.to_date_int_val());
175
40
}
176
177
template <>
178
1.23k
inline size_t hash_crc32(doris::DateV2Value<doris::DateV2ValueType> u) {
179
1.23k
    return hash_crc32(u.to_date_int_val());
180
1.23k
}
181
182
template <>
183
6
inline size_t hash_crc32(doris::TimeStampNsValue u) {
184
6
    return hash_crc32(u.epoch_nanos());
185
6
}
186
187
template <>
188
0
inline size_t hash_crc32(doris::TimestampTzValue u) {
189
0
    return hash_crc32(u.to_date_int_val());
190
0
}
191
192
#define DEFINE_HASH(T)                   \
193
    template <>                          \
194
    struct HashCRC32<T> {                \
195
26.8M
        size_t operator()(T key) const { \
196
26.8M
            return hash_crc32<T>(key);   \
197
26.8M
        }                                \
_ZNK9HashCRC32IhEclEh
Line
Count
Source
195
451k
        size_t operator()(T key) const { \
196
451k
            return hash_crc32<T>(key);   \
197
451k
        }                                \
_ZNK9HashCRC32ItEclEt
Line
Count
Source
195
21.1k
        size_t operator()(T key) const { \
196
21.1k
            return hash_crc32<T>(key);   \
197
21.1k
        }                                \
_ZNK9HashCRC32IjEclEj
Line
Count
Source
195
16.5M
        size_t operator()(T key) const { \
196
16.5M
            return hash_crc32<T>(key);   \
197
16.5M
        }                                \
_ZNK9HashCRC32ImEclEm
Line
Count
Source
195
5.82M
        size_t operator()(T key) const { \
196
5.82M
            return hash_crc32<T>(key);   \
197
5.82M
        }                                \
_ZNK9HashCRC32IN4wide7integerILm128EjEEEclES2_
Line
Count
Source
195
3.48M
        size_t operator()(T key) const { \
196
3.48M
            return hash_crc32<T>(key);   \
197
3.48M
        }                                \
_ZNK9HashCRC32IaEclEa
Line
Count
Source
195
8.92k
        size_t operator()(T key) const { \
196
8.92k
            return hash_crc32<T>(key);   \
197
8.92k
        }                                \
_ZNK9HashCRC32IsEclEs
Line
Count
Source
195
8.50k
        size_t operator()(T key) const { \
196
8.50k
            return hash_crc32<T>(key);   \
197
8.50k
        }                                \
_ZNK9HashCRC32IiEclEi
Line
Count
Source
195
202k
        size_t operator()(T key) const { \
196
202k
            return hash_crc32<T>(key);   \
197
202k
        }                                \
_ZNK9HashCRC32IlEclEl
Line
Count
Source
195
248k
        size_t operator()(T key) const { \
196
248k
            return hash_crc32<T>(key);   \
197
248k
        }                                \
_ZNK9HashCRC32InEclEn
Line
Count
Source
195
264
        size_t operator()(T key) const { \
196
264
            return hash_crc32<T>(key);   \
197
264
        }                                \
Unexecuted instantiation: _ZNK9HashCRC32IfEclEf
_ZNK9HashCRC32IdEclEd
Line
Count
Source
195
5
        size_t operator()(T key) const { \
196
5
            return hash_crc32<T>(key);   \
197
5
        }                                \
Unexecuted instantiation: _ZNK9HashCRC32IN5doris16VecDateTimeValueEEclES1_
_ZNK9HashCRC32IN5doris11DateV2ValueINS0_19DateTimeV2ValueTypeEEEEclES3_
Line
Count
Source
195
40
        size_t operator()(T key) const { \
196
40
            return hash_crc32<T>(key);   \
197
40
        }                                \
_ZNK9HashCRC32IN5doris11DateV2ValueINS0_15DateV2ValueTypeEEEEclES3_
Line
Count
Source
195
1.23k
        size_t operator()(T key) const { \
196
1.23k
            return hash_crc32<T>(key);   \
197
1.23k
        }                                \
_ZNK9HashCRC32IN5doris16TimeStampNsValueEEclES1_
Line
Count
Source
195
6
        size_t operator()(T key) const { \
196
6
            return hash_crc32<T>(key);   \
197
6
        }                                \
Unexecuted instantiation: _ZNK9HashCRC32IN5doris16TimestampTzValueEEclES1_
_ZNK9HashCRC32IoEclEo
Line
Count
Source
195
34
        size_t operator()(T key) const { \
196
34
            return hash_crc32<T>(key);   \
197
34
        }                                \
198
    };
199
200
DEFINE_HASH(doris::UInt8)
201
DEFINE_HASH(doris::UInt16)
202
DEFINE_HASH(doris::UInt32)
203
DEFINE_HASH(doris::UInt64)
204
DEFINE_HASH(doris::UInt128)
205
DEFINE_HASH(doris::Int8)
206
DEFINE_HASH(doris::Int16)
207
DEFINE_HASH(doris::Int32)
208
DEFINE_HASH(doris::Int64)
209
DEFINE_HASH(doris::Int128)
210
DEFINE_HASH(doris::Float32)
211
DEFINE_HASH(doris::Float64)
212
DEFINE_HASH(doris::VecDateTimeValue)
213
DEFINE_HASH(doris::DateV2Value<doris::DateTimeV2ValueType>)
214
DEFINE_HASH(doris::DateV2Value<doris::DateV2ValueType>)
215
DEFINE_HASH(doris::TimeStampNsValue)
216
DEFINE_HASH(doris::TimestampTzValue)
217
DEFINE_HASH(unsigned __int128)
218
219
#undef DEFINE_HASH
220
221
template <typename Key, typename Hash = HashCRC32<Key>>
222
struct HashMixWrapper {
223
15.9M
    size_t operator()(Key key) const { return phmap::phmap_mix<sizeof(size_t)>()(Hash()(key)); }
_ZNK14HashMixWrapperIj9HashCRC32IjEEclEj
Line
Count
Source
223
15.3M
    size_t operator()(Key key) const { return phmap::phmap_mix<sizeof(size_t)>()(Hash()(key)); }
_ZNK14HashMixWrapperIm9HashCRC32ImEEclEm
Line
Count
Source
223
566k
    size_t operator()(Key key) const { return phmap::phmap_mix<sizeof(size_t)>()(Hash()(key)); }
224
};
225
226
template <>
227
struct HashCRC32<doris::UInt256> {
228
74.3k
    size_t operator()(const doris::UInt256& x) const {
229
74.3k
#if defined(__SSE4_2__) || defined(__aarch64__)
230
74.3k
        doris::UInt64 crc = -1ULL;
231
74.3k
        crc = _mm_crc32_u64(crc, x.items[0]);
232
74.3k
        crc = _mm_crc32_u64(crc, x.items[1]);
233
74.3k
        crc = _mm_crc32_u64(crc, x.items[2]);
234
74.3k
        crc = _mm_crc32_u64(crc, x.items[3]);
235
74.3k
        return crc;
236
#else
237
        return Hash128to64({Hash128to64({x.a, x.b}), Hash128to64({x.c, x.d})});
238
#endif
239
74.3k
    }
240
};
241
242
template <>
243
struct HashCRC32<wide::Int256> {
244
8.30k
    size_t operator()(const wide::Int256& x) const {
245
8.30k
#if defined(__SSE4_2__) || defined(__aarch64__)
246
8.30k
        doris::UInt64 crc = -1ULL;
247
8.30k
        crc = _mm_crc32_u64(crc, x.items[0]);
248
8.30k
        crc = _mm_crc32_u64(crc, x.items[1]);
249
8.30k
        crc = _mm_crc32_u64(crc, x.items[2]);
250
8.30k
        crc = _mm_crc32_u64(crc, x.items[3]);
251
8.30k
        return crc;
252
#else
253
        return Hash128to64(
254
                {Hash128to64({x.items[0], x.items[1]}), Hash128to64({x.items[2], x.items[3]})});
255
#endif
256
8.30k
    }
257
};
258
259
template <>
260
struct HashCRC32<doris::Decimal256> {
261
0
    size_t operator()(const doris::Decimal256& value) const {
262
0
        return HashCRC32<wide::Int256>()(value.value);
263
0
    }
264
};
265
266
template <>
267
struct HashCRC32<doris::Decimal32> {
268
0
    size_t operator()(const doris::Decimal32& value) const {
269
0
        return HashCRC32<int32_t>()(value.value);
270
0
    }
271
};
272
273
template <>
274
struct HashCRC32<doris::Decimal64> {
275
20
    size_t operator()(const doris::Decimal64& value) const {
276
20
        return HashCRC32<int64_t>()(value.value);
277
20
    }
278
};
279
280
template <>
281
struct HashCRC32<doris::Decimal128V3> {
282
39
    size_t operator()(const doris::Decimal128V3& value) const {
283
39
        return HashCRC32<__int128>()(value.value);
284
39
    }
285
};
286
287
template <>
288
struct HashCRC32<doris::Decimal128V2> {
289
0
    size_t operator()(const doris::Decimal128V2& value) const {
290
0
        return HashCRC32<__int128>()(value.value);
291
0
    }
292
};
293
294
template <>
295
struct HashCRC32<doris::DecimalV2Value> {
296
0
    size_t operator()(const doris::DecimalV2Value& value) const {
297
0
        return HashCRC32<__int128>()(value.value());
298
0
    }
299
};
300
301
#include "common/compile_check_avoid_begin.h"
302
303
template <>
304
struct HashCRC32<doris::UInt72> {
305
78.2k
    size_t operator()(const doris::UInt72& x) const {
306
78.2k
        doris::UInt64 crc = -1ULL;
307
78.2k
        crc = _mm_crc32_u8(crc, x.a);
308
78.2k
        crc = _mm_crc32_u64(crc, x.b);
309
78.2k
        return crc;
310
78.2k
    }
311
};
312
313
template <>
314
struct HashCRC32<doris::UInt96> {
315
30.2k
    size_t operator()(const doris::UInt96& x) const {
316
30.2k
        doris::UInt64 crc = -1ULL;
317
30.2k
        crc = _mm_crc32_u32(crc, x.a);
318
30.2k
        crc = _mm_crc32_u64(crc, x.b);
319
30.2k
        return crc;
320
30.2k
    }
321
};
322
323
template <>
324
struct HashCRC32<doris::UInt104> {
325
4.46k
    size_t operator()(const doris::UInt104& x) const {
326
4.46k
        doris::UInt64 crc = -1ULL;
327
4.46k
        crc = _mm_crc32_u8(crc, x.a);
328
4.46k
        crc = _mm_crc32_u32(crc, x.b);
329
4.46k
        crc = _mm_crc32_u64(crc, x.c);
330
4.46k
        return crc;
331
4.46k
    }
332
};
333
334
template <>
335
struct HashCRC32<doris::UInt136> {
336
39.7k
    size_t operator()(const doris::UInt136& x) const {
337
39.7k
        doris::UInt64 crc = -1ULL;
338
39.7k
        crc = _mm_crc32_u8(crc, x.a);
339
39.7k
        crc = _mm_crc32_u64(crc, x.b);
340
39.7k
        crc = _mm_crc32_u64(crc, x.c);
341
39.7k
        return crc;
342
39.7k
    }
343
};
344
345
#include "common/compile_check_avoid_end.h"