/root/doris/be/src/vec/common/uint128.h
Line | Count | Source (jump to first uncovered line) |
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/Uint128.h |
19 | | // and modified by Doris |
20 | | |
21 | | #pragma once |
22 | | |
23 | | #include <iomanip> |
24 | | #include <sstream> |
25 | | #include <tuple> |
26 | | |
27 | | #include "gutil/hash/city.h" |
28 | | #include "gutil/hash/hash128to64.h" |
29 | | #include "util/sse_util.hpp" |
30 | | #include "vec/core/types.h" |
31 | | |
32 | | namespace doris::vectorized { |
33 | | |
34 | | /// For aggregation by SipHash, UUID type or concatenation of several fields. |
35 | | struct UInt128 { |
36 | | /// This naming assumes little endian. |
37 | | UInt64 low; |
38 | | UInt64 high; |
39 | | |
40 | | UInt128() = default; |
41 | 10 | explicit UInt128(const UInt64 low_, const UInt64 high_) : low(low_), high(high_) {} |
42 | 25 | explicit UInt128(const UInt64 rhs) : low(rhs), high() {} |
43 | | |
44 | 1.25k | auto tuple() const { return std::tie(high, low); } |
45 | | |
46 | 0 | String to_hex_string() const { |
47 | 0 | std::ostringstream os; |
48 | 0 | os << std::setw(16) << std::setfill('0') << std::hex << high << low; |
49 | 0 | return String(os.str()); |
50 | 0 | } |
51 | | |
52 | 625 | bool operator==(const UInt128 rhs) const { return tuple() == rhs.tuple(); } |
53 | 0 | auto operator<=>(const UInt128 rhs) const { return tuple() <=> rhs.tuple(); } |
54 | | |
55 | 10 | UInt128 operator<<(const UInt128& rhs) const { |
56 | 10 | const uint64_t shift = rhs.low; |
57 | 10 | if (((bool)rhs.high) || (shift >= 128)) { |
58 | 0 | return UInt128(0); |
59 | 10 | } else if (shift == 64) { |
60 | 10 | return UInt128(0, low); |
61 | 10 | } else if (shift == 0) { |
62 | 0 | return *this; |
63 | 0 | } else if (shift < 64) { |
64 | 0 | return UInt128(low << shift, (high << shift) + (low >> (64 - shift))); |
65 | 0 | } else if ((128 > shift) && (shift > 64)) { |
66 | 0 | return UInt128(0, low << (shift - 64)); |
67 | 0 | } else { |
68 | 0 | return UInt128(0); |
69 | 0 | } |
70 | 10 | } |
71 | | |
72 | 10 | UInt128& operator<<=(const UInt128& rhs) { |
73 | 10 | *this = *this << rhs; |
74 | 10 | return *this; |
75 | 10 | } |
76 | | |
77 | 0 | UInt128 operator+(const UInt128& rhs) const { |
78 | 0 | return UInt128(low + rhs.low, high + rhs.high + ((low + rhs.low) < low)); |
79 | 0 | } |
80 | | |
81 | 10 | UInt128& operator+=(const UInt128& rhs) { |
82 | 10 | high += rhs.high + ((low + rhs.low) < low); |
83 | 10 | low += rhs.low; |
84 | 10 | return *this; |
85 | 10 | } |
86 | | |
87 | | template <typename T> |
88 | 0 | bool operator==(const T rhs) const { |
89 | 0 | return *this == UInt128(rhs); |
90 | 0 | } |
91 | | template <typename T> |
92 | | bool operator!=(const T rhs) const { |
93 | | return *this != UInt128(rhs); |
94 | | } |
95 | | template <typename T> |
96 | | bool operator>=(const T rhs) const { |
97 | | return *this >= UInt128(rhs); |
98 | | } |
99 | | template <typename T> |
100 | | bool operator>(const T rhs) const { |
101 | | return *this > UInt128(rhs); |
102 | | } |
103 | | template <typename T> |
104 | | bool operator<=(const T rhs) const { |
105 | | return *this <= UInt128(rhs); |
106 | | } |
107 | | template <typename T> |
108 | | bool operator<(const T rhs) const { |
109 | | return *this < UInt128(rhs); |
110 | | } |
111 | | |
112 | | template <typename T> |
113 | 0 | explicit operator T() const { |
114 | 0 | return static_cast<T>(low); |
115 | 0 | } Unexecuted instantiation: _ZNK5doris10vectorized7UInt128cvT_IiEEv Unexecuted instantiation: _ZNK5doris10vectorized7UInt128cvT_IdEEv Unexecuted instantiation: _ZNK5doris10vectorized7UInt128cvT_ImEEv Unexecuted instantiation: _ZNK5doris10vectorized7UInt128cvT_IbEEv Unexecuted instantiation: _ZNK5doris10vectorized7UInt128cvT_IlEEv |
116 | | |
117 | 0 | UInt128& operator=(const UInt64 rhs) { |
118 | 0 | low = rhs; |
119 | 0 | high = 0; |
120 | 0 | return *this; |
121 | 0 | } |
122 | | }; |
123 | | |
124 | | template <typename T> |
125 | | bool inline operator==(T a, const UInt128 b) { |
126 | | return UInt128(a) == b; |
127 | | } |
128 | | template <typename T> |
129 | | bool inline operator!=(T a, const UInt128 b) { |
130 | | return UInt128(a) != b; |
131 | | } |
132 | | template <typename T> |
133 | | bool inline operator>=(T a, const UInt128 b) { |
134 | | return UInt128(a) >= b; |
135 | | } |
136 | | template <typename T> |
137 | | bool inline operator>(T a, const UInt128 b) { |
138 | | return UInt128(a) > b; |
139 | | } |
140 | | template <typename T> |
141 | | bool inline operator<=(T a, const UInt128 b) { |
142 | | return UInt128(a) <= b; |
143 | | } |
144 | | template <typename T> |
145 | | bool inline operator<(T a, const UInt128 b) { |
146 | | return UInt128(a) < b; |
147 | | } |
148 | | |
149 | | template <> |
150 | | inline constexpr bool IsNumber<UInt128> = true; |
151 | | template <> |
152 | | struct TypeName<UInt128> { |
153 | 0 | static const char* get() { return "UInt128"; } |
154 | | }; |
155 | | template <> |
156 | | struct TypeId<UInt128> { |
157 | | static constexpr const TypeIndex value = TypeIndex::UInt128; |
158 | | }; |
159 | | |
160 | | struct UInt128Hash { |
161 | 680 | size_t operator()(UInt128 x) const { return Hash128to64({x.low, x.high}); } |
162 | | }; |
163 | | |
164 | | #if defined(__SSE4_2__) || defined(__aarch64__) |
165 | | |
166 | | struct UInt128HashCRC32 { |
167 | 0 | size_t operator()(UInt128 x) const { |
168 | 0 | UInt64 crc = -1ULL; |
169 | 0 | crc = _mm_crc32_u64(crc, x.low); |
170 | 0 | crc = _mm_crc32_u64(crc, x.high); |
171 | 0 | return crc; |
172 | 0 | } |
173 | | }; |
174 | | |
175 | | #else |
176 | | |
177 | | /// On other platforms we do not use CRC32. NOTE This can be confusing. |
178 | | struct UInt128HashCRC32 : public UInt128Hash {}; |
179 | | |
180 | | #endif |
181 | | |
182 | | struct UInt128TrivialHash { |
183 | 0 | size_t operator()(UInt128 x) const { return x.low; } |
184 | | }; |
185 | | |
186 | | /** Used for aggregation, for putting a large number of constant-length keys in a hash table. |
187 | | */ |
188 | | struct UInt256 { |
189 | | UInt64 a; |
190 | | UInt64 b; |
191 | | UInt64 c; |
192 | | UInt64 d; |
193 | | |
194 | 0 | bool operator==(const UInt256 rhs) const { |
195 | 0 | return a == rhs.a && b == rhs.b && c == rhs.c && d == rhs.d; |
196 | 0 | } |
197 | | |
198 | 0 | bool operator!=(const UInt256 rhs) const { return !operator==(rhs); } |
199 | | |
200 | 0 | bool operator==(const UInt64 rhs) const { return a == rhs && b == 0 && c == 0 && d == 0; } |
201 | 0 | bool operator!=(const UInt64 rhs) const { return !operator==(rhs); } |
202 | | |
203 | 0 | UInt256& operator=(const UInt64 rhs) { |
204 | 0 | a = rhs; |
205 | 0 | b = 0; |
206 | 0 | c = 0; |
207 | 0 | d = 0; |
208 | 0 | return *this; |
209 | 0 | } |
210 | | }; |
211 | | } // namespace doris::vectorized |
212 | | |
213 | | /// Overload hash for type casting |
214 | | template <> |
215 | | struct std::hash<doris::vectorized::UInt128> { |
216 | 0 | size_t operator()(const doris::vectorized::UInt128& u) const { |
217 | 0 | return Hash128to64({u.low, u.high}); |
218 | 0 | } |
219 | | }; |
220 | | |
221 | | template <> |
222 | | struct std::is_signed<doris::vectorized::UInt128> { |
223 | | static constexpr bool value = false; |
224 | | }; |
225 | | |
226 | | template <> |
227 | | struct std::is_unsigned<doris::vectorized::UInt128> { |
228 | | static constexpr bool value = true; |
229 | | }; |
230 | | |
231 | | template <> |
232 | | struct std::is_integral<doris::vectorized::UInt128> { |
233 | | static constexpr bool value = true; |
234 | | }; |
235 | | |
236 | | // Operator +, -, /, *, % aren't implemented, so it's not an arithmetic type |
237 | | template <> |
238 | | struct std::is_arithmetic<doris::vectorized::UInt128> { |
239 | | static constexpr bool value = false; |
240 | | }; |