Coverage Report

Created: 2026-03-17 19:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/core/wide_integer.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
///////////////////////////////////////////////////////////////
18
//  Distributed under the Boost Software License, Version 1.0.
19
//  (See at http://www.boost.org/LICENSE_1_0.txt)
20
///////////////////////////////////////////////////////////////
21
22
/*  Divide and multiply
23
 *
24
 *
25
 * Copyright (c) 2008
26
 * Evan Teran
27
 *
28
 * Permission to use, copy, modify, and distribute this software and its
29
 * documentation for any purpose and without fee is hereby granted, provided
30
 * that the above copyright notice appears in all copies and that both the
31
 * copyright notice and this permission notice appear in supporting
32
 * documentation, and that the same name not be used in advertising or
33
 * publicity pertaining to distribution of the software without specific,
34
 * written prior permission. We make no representations about the
35
 * suitability this software for any purpose. It is provided "as is"
36
 * without express or implied warranty.
37
 */
38
// This file is copied from
39
// https://github.com/ClickHouse/ClickHouse/blob/master/base/base/wide_integer.h
40
// and modified by Doris
41
#pragma once
42
43
#include <cstdint>
44
#include <initializer_list>
45
#include <iomanip>
46
#include <iostream>
47
#include <limits>
48
#include <sstream>
49
#include <string>
50
#include <type_traits>
51
52
// NOLINTBEGIN(*)
53
54
namespace wide {
55
template <size_t Bits, typename Signed>
56
class integer;
57
}
58
59
namespace std {
60
61
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
62
struct common_type<wide::integer<Bits, Signed>, wide::integer<Bits2, Signed2>>;
63
64
template <size_t Bits, typename Signed, typename Arithmetic>
65
struct common_type<wide::integer<Bits, Signed>, Arithmetic>;
66
67
template <typename Arithmetic, size_t Bits, typename Signed>
68
struct common_type<Arithmetic, wide::integer<Bits, Signed>>;
69
70
} // namespace std
71
72
namespace wide {
73
74
template <size_t Bits, typename Signed>
75
class integer {
76
public:
77
    using base_type = uint64_t;
78
    using signed_base_type = int64_t;
79
80
    static constexpr size_t item_count = Bits / 8 / sizeof(base_type);
81
82
    // ctors
83
    constexpr integer() noexcept = default;
84
85
    template <size_t Bits2, typename Signed2>
86
    constexpr integer(const integer<Bits2, Signed2> rhs) noexcept;
87
88
    template <typename T>
89
        requires(std::is_arithmetic_v<T> || std::is_same_v<T, __int128> ||
90
                 std::is_same_v<T, unsigned __int128>)
91
    constexpr integer(T rhs) noexcept;
92
93
    template <typename T>
94
    constexpr integer(std::initializer_list<T> il) noexcept;
95
96
    // assignment
97
    template <size_t Bits2, typename Signed2>
98
    constexpr integer<Bits, Signed>& operator=(const integer<Bits2, Signed2>& rhs) noexcept;
99
100
    template <typename Arithmetic>
101
    constexpr integer<Bits, Signed>& operator=(Arithmetic rhs) noexcept;
102
103
    template <typename Arithmetic>
104
    constexpr integer<Bits, Signed>& operator*=(const Arithmetic& rhs);
105
106
    template <typename Arithmetic>
107
    constexpr integer<Bits, Signed>& operator/=(const Arithmetic& rhs);
108
109
    template <typename Arithmetic>
110
    constexpr integer<Bits, Signed>& operator+=(const Arithmetic& rhs) noexcept(
111
            std::is_same_v<Signed, unsigned>);
112
113
    template <typename Arithmetic>
114
    constexpr integer<Bits, Signed>& operator-=(const Arithmetic& rhs) noexcept(
115
            std::is_same_v<Signed, unsigned>);
116
117
    template <typename Integral>
118
    constexpr integer<Bits, Signed>& operator%=(const Integral& rhs);
119
120
    template <typename Integral>
121
    constexpr integer<Bits, Signed>& operator&=(const Integral& rhs) noexcept;
122
123
    template <typename Integral>
124
    constexpr integer<Bits, Signed>& operator|=(const Integral& rhs) noexcept;
125
126
    template <typename Integral>
127
    constexpr integer<Bits, Signed>& operator^=(const Integral& rhs) noexcept;
128
129
    constexpr integer<Bits, Signed>& operator<<=(int n) noexcept;
130
    constexpr integer<Bits, Signed>& operator>>=(int n) noexcept;
131
132
    constexpr integer<Bits, Signed>& operator++() noexcept(std::is_same_v<Signed, unsigned>);
133
    constexpr integer<Bits, Signed> operator++(int) noexcept(std::is_same_v<Signed, unsigned>);
134
    constexpr integer<Bits, Signed>& operator--() noexcept(std::is_same_v<Signed, unsigned>);
135
    constexpr integer<Bits, Signed> operator--(int) noexcept(std::is_same_v<Signed, unsigned>);
136
137
    // observers
138
139
    constexpr explicit operator bool() const noexcept;
140
141
    template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>, T>>
142
    constexpr operator T() const noexcept;
143
144
    constexpr operator long double() const noexcept;
145
    constexpr operator double() const noexcept;
146
    constexpr operator float() const noexcept;
147
148
    std::string to_hex_string() const;
149
150
    struct _impl;
151
152
    base_type items[item_count];
153
154
799k
    uint64_t low() const {
155
799k
        static_assert(item_count == 2);
156
799k
        return items[0];
157
799k
    }
158
111k
    uint64_t high() const {
159
111k
        static_assert(item_count == 2);
160
111k
        return items[1];
161
111k
    }
162
163
private:
164
    template <size_t Bits2, typename Signed2>
165
    friend class integer;
166
167
    friend class std::numeric_limits<integer<Bits, signed>>;
168
    friend class std::numeric_limits<integer<Bits, unsigned>>;
169
};
170
171
template <typename T>
172
static constexpr bool ArithmeticConcept() noexcept;
173
174
template <class T1, class T2>
175
using _only_arithmetic =
176
        typename std::enable_if<ArithmeticConcept<T1>() && ArithmeticConcept<T2>()>::type;
177
178
template <typename T>
179
static constexpr bool IntegralConcept() noexcept;
180
181
template <class T, class T2>
182
using _only_integer = typename std::enable_if<IntegralConcept<T>() && IntegralConcept<T2>()>::type;
183
184
// Unary operators
185
template <size_t Bits, typename Signed>
186
constexpr integer<Bits, Signed> operator~(const integer<Bits, Signed>& lhs) noexcept;
187
188
template <size_t Bits, typename Signed>
189
constexpr integer<Bits, Signed> operator-(const integer<Bits, Signed>& lhs) noexcept(
190
        std::is_same_v<Signed, unsigned>);
191
192
template <size_t Bits, typename Signed>
193
constexpr integer<Bits, Signed> operator+(const integer<Bits, Signed>& lhs) noexcept(
194
        std::is_same_v<Signed, unsigned>);
195
196
// Binary operators
197
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
198
std::common_type_t<integer<Bits, Signed>, integer<Bits2, Signed2>> constexpr operator*(
199
        const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
200
template <typename Arithmetic, typename Arithmetic2,
201
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
202
std::common_type_t<Arithmetic, Arithmetic2> constexpr operator*(const Arithmetic& rhs,
203
                                                                const Arithmetic2& lhs);
204
205
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
206
std::common_type_t<integer<Bits, Signed>, integer<Bits2, Signed2>> constexpr operator/(
207
        const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
208
template <typename Arithmetic, typename Arithmetic2,
209
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
210
std::common_type_t<Arithmetic, Arithmetic2> constexpr operator/(const Arithmetic& rhs,
211
                                                                const Arithmetic2& lhs);
212
213
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
214
std::common_type_t<integer<Bits, Signed>, integer<Bits2, Signed2>> constexpr operator+(
215
        const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
216
template <typename Arithmetic, typename Arithmetic2,
217
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
218
std::common_type_t<Arithmetic, Arithmetic2> constexpr operator+(const Arithmetic& rhs,
219
                                                                const Arithmetic2& lhs);
220
221
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
222
std::common_type_t<integer<Bits, Signed>, integer<Bits2, Signed2>> constexpr operator-(
223
        const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
224
template <typename Arithmetic, typename Arithmetic2,
225
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
226
std::common_type_t<Arithmetic, Arithmetic2> constexpr operator-(const Arithmetic& rhs,
227
                                                                const Arithmetic2& lhs);
228
229
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
230
std::common_type_t<integer<Bits, Signed>, integer<Bits2, Signed2>> constexpr operator%(
231
        const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
232
template <typename Integral, typename Integral2, class = _only_integer<Integral, Integral2>>
233
std::common_type_t<Integral, Integral2> constexpr operator%(const Integral& rhs,
234
                                                            const Integral2& lhs);
235
236
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
237
std::common_type_t<integer<Bits, Signed>, integer<Bits2, Signed2>> constexpr operator&(
238
        const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
239
template <typename Integral, typename Integral2, class = _only_integer<Integral, Integral2>>
240
std::common_type_t<Integral, Integral2> constexpr operator&(const Integral& rhs,
241
                                                            const Integral2& lhs);
242
243
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
244
std::common_type_t<integer<Bits, Signed>, integer<Bits2, Signed2>> constexpr operator|(
245
        const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
246
template <typename Integral, typename Integral2, class = _only_integer<Integral, Integral2>>
247
std::common_type_t<Integral, Integral2> constexpr operator|(const Integral& rhs,
248
                                                            const Integral2& lhs);
249
250
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
251
std::common_type_t<integer<Bits, Signed>, integer<Bits2, Signed2>> constexpr operator^(
252
        const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
253
template <typename Integral, typename Integral2, class = _only_integer<Integral, Integral2>>
254
std::common_type_t<Integral, Integral2> constexpr operator^(const Integral& rhs,
255
                                                            const Integral2& lhs);
256
257
// TODO: Integral
258
template <size_t Bits, typename Signed>
259
constexpr integer<Bits, Signed> operator<<(const integer<Bits, Signed>& lhs, int n) noexcept;
260
261
template <size_t Bits, typename Signed>
262
constexpr integer<Bits, Signed> operator>>(const integer<Bits, Signed>& lhs, int n) noexcept;
263
264
template <size_t Bits, typename Signed, typename Int,
265
          typename = std::enable_if_t<!std::is_same_v<Int, int>>>
266
102
constexpr integer<Bits, Signed> operator<<(const integer<Bits, Signed>& lhs, Int n) noexcept {
267
102
    return lhs << int(n);
268
102
}
269
template <size_t Bits, typename Signed, typename Int,
270
          typename = std::enable_if_t<!std::is_same_v<Int, int>>>
271
0
constexpr integer<Bits, Signed> operator>>(const integer<Bits, Signed>& lhs, Int n) noexcept {
272
0
    return lhs >> int(n);
273
0
}
274
275
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
276
constexpr bool operator<(const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
277
template <typename Arithmetic, typename Arithmetic2,
278
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
279
constexpr bool operator<(const Arithmetic& rhs, const Arithmetic2& lhs);
280
281
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
282
constexpr bool operator>(const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
283
template <typename Arithmetic, typename Arithmetic2,
284
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
285
constexpr bool operator>(const Arithmetic& rhs, const Arithmetic2& lhs);
286
287
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
288
constexpr bool operator<=(const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
289
template <typename Arithmetic, typename Arithmetic2,
290
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
291
constexpr bool operator<=(const Arithmetic& rhs, const Arithmetic2& lhs);
292
293
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
294
constexpr bool operator>=(const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
295
template <typename Arithmetic, typename Arithmetic2,
296
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
297
constexpr bool operator>=(const Arithmetic& rhs, const Arithmetic2& lhs);
298
299
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
300
constexpr bool operator==(const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
301
template <typename Arithmetic, typename Arithmetic2,
302
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
303
constexpr bool operator==(const Arithmetic& rhs, const Arithmetic2& lhs);
304
305
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
306
constexpr bool operator!=(const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
307
template <typename Arithmetic, typename Arithmetic2,
308
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
309
constexpr bool operator!=(const Arithmetic& rhs, const Arithmetic2& lhs);
310
311
template <size_t Bits, typename Signed, size_t Bits2, typename Signed2>
312
constexpr auto operator<=>(const integer<Bits, Signed>& lhs, const integer<Bits2, Signed2>& rhs);
313
template <typename Arithmetic, typename Arithmetic2,
314
          class = _only_arithmetic<Arithmetic, Arithmetic2>>
315
constexpr auto operator<=>(const Arithmetic& rhs, const Arithmetic2& lhs);
316
317
} // namespace wide
318
319
// NOLINTEND(*)
320
321
#include "core/wide_integer_impl.h"
322
323
namespace wide {
324
325
template <size_t Bits, typename Signed>
326
0
inline std::string integer<Bits, Signed>::to_hex_string() const {
327
0
    std::ostringstream os;
328
0
    os << std::setw(16) << std::setfill('0') << std::hex;
329
0
    for (size_t i = 0; i < item_count; i++) {
330
0
        os << items[i];
331
0
    }
332
0
    return os.str();
333
0
}
334
335
} // namespace wide