Coverage Report

Created: 2024-11-18 10:37

/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
};