Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libc/src/__support/big_int.h
213766 views
1
//===-- A class to manipulate wide integers. --------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLVM_LIBC_SRC___SUPPORT_BIG_INT_H
10
#define LLVM_LIBC_SRC___SUPPORT_BIG_INT_H
11
12
#include "src/__support/CPP/array.h"
13
#include "src/__support/CPP/bit.h" // countl_zero
14
#include "src/__support/CPP/limits.h"
15
#include "src/__support/CPP/optional.h"
16
#include "src/__support/CPP/type_traits.h"
17
#include "src/__support/macros/attributes.h" // LIBC_INLINE
18
#include "src/__support/macros/config.h"
19
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
20
#include "src/__support/macros/properties/compiler.h" // LIBC_COMPILER_IS_CLANG
21
#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128, LIBC_TYPES_HAS_INT64
22
#include "src/__support/math_extras.h" // add_with_carry, sub_with_borrow
23
#include "src/__support/number_pair.h"
24
25
#include <stddef.h> // For size_t
26
#include <stdint.h>
27
28
namespace LIBC_NAMESPACE_DECL {
29
30
namespace multiword {
31
32
// A type trait mapping unsigned integers to their half-width unsigned
33
// counterparts.
34
template <typename T> struct half_width;
35
template <> struct half_width<uint16_t> : cpp::type_identity<uint8_t> {};
36
template <> struct half_width<uint32_t> : cpp::type_identity<uint16_t> {};
37
#ifdef LIBC_TYPES_HAS_INT64
38
template <> struct half_width<uint64_t> : cpp::type_identity<uint32_t> {};
39
#ifdef LIBC_TYPES_HAS_INT128
40
template <> struct half_width<__uint128_t> : cpp::type_identity<uint64_t> {};
41
#endif // LIBC_TYPES_HAS_INT128
42
#endif // LIBC_TYPES_HAS_INT64
43
template <typename T> using half_width_t = typename half_width<T>::type;
44
45
// An array of two elements that can be used in multiword operations.
46
template <typename T> struct DoubleWide final : cpp::array<T, 2> {
47
using UP = cpp::array<T, 2>;
48
using UP::UP;
49
LIBC_INLINE constexpr DoubleWide(T lo, T hi) : UP({lo, hi}) {}
50
};
51
52
// Converts an unsigned value into a DoubleWide<half_width_t<T>>.
53
template <typename T> LIBC_INLINE constexpr auto split(T value) {
54
static_assert(cpp::is_unsigned_v<T>);
55
using half_type = half_width_t<T>;
56
return DoubleWide<half_type>(
57
half_type(value),
58
half_type(value >> cpp::numeric_limits<half_type>::digits));
59
}
60
61
// The low part of a DoubleWide value.
62
template <typename T> LIBC_INLINE constexpr T lo(const DoubleWide<T> &value) {
63
return value[0];
64
}
65
// The high part of a DoubleWide value.
66
template <typename T> LIBC_INLINE constexpr T hi(const DoubleWide<T> &value) {
67
return value[1];
68
}
69
// The low part of an unsigned value.
70
template <typename T> LIBC_INLINE constexpr half_width_t<T> lo(T value) {
71
return lo(split(value));
72
}
73
// The high part of an unsigned value.
74
template <typename T> LIBC_INLINE constexpr half_width_t<T> hi(T value) {
75
return hi(split(value));
76
}
77
78
// Returns 'a' times 'b' in a DoubleWide<word>. Cannot overflow by construction.
79
template <typename word>
80
LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) {
81
if constexpr (cpp::is_same_v<word, uint8_t>) {
82
return split<uint16_t>(uint16_t(a) * uint16_t(b));
83
} else if constexpr (cpp::is_same_v<word, uint16_t>) {
84
return split<uint32_t>(uint32_t(a) * uint32_t(b));
85
}
86
#ifdef LIBC_TYPES_HAS_INT64
87
else if constexpr (cpp::is_same_v<word, uint32_t>) {
88
return split<uint64_t>(uint64_t(a) * uint64_t(b));
89
}
90
#endif
91
#ifdef LIBC_TYPES_HAS_INT128
92
else if constexpr (cpp::is_same_v<word, uint64_t>) {
93
return split<__uint128_t>(__uint128_t(a) * __uint128_t(b));
94
}
95
#endif
96
else {
97
using half_word = half_width_t<word>;
98
const auto shiftl = [](word value) -> word {
99
return value << cpp::numeric_limits<half_word>::digits;
100
};
101
const auto shiftr = [](word value) -> word {
102
return value >> cpp::numeric_limits<half_word>::digits;
103
};
104
// Here we do a one digit multiplication where 'a' and 'b' are of type
105
// word. We split 'a' and 'b' into half words and perform the classic long
106
// multiplication with 'a' and 'b' being two-digit numbers.
107
108
// a a_hi a_lo
109
// x b => x b_hi b_lo
110
// ---- -----------
111
// c result
112
// We convert 'lo' and 'hi' from 'half_word' to 'word' so multiplication
113
// doesn't overflow.
114
const word a_lo = lo(a);
115
const word b_lo = lo(b);
116
const word a_hi = hi(a);
117
const word b_hi = hi(b);
118
const word step1 = b_lo * a_lo; // no overflow;
119
const word step2 = b_lo * a_hi; // no overflow;
120
const word step3 = b_hi * a_lo; // no overflow;
121
const word step4 = b_hi * a_hi; // no overflow;
122
word lo_digit = step1;
123
word hi_digit = step4;
124
const word no_carry = 0;
125
word carry;
126
word _; // unused carry variable.
127
lo_digit = add_with_carry<word>(lo_digit, shiftl(step2), no_carry, carry);
128
hi_digit = add_with_carry<word>(hi_digit, shiftr(step2), carry, _);
129
lo_digit = add_with_carry<word>(lo_digit, shiftl(step3), no_carry, carry);
130
hi_digit = add_with_carry<word>(hi_digit, shiftr(step3), carry, _);
131
return DoubleWide<word>(lo_digit, hi_digit);
132
}
133
}
134
135
// In-place 'dst op= rhs' with operation with carry propagation. Returns carry.
136
template <typename Function, typename word, size_t N, size_t M>
137
LIBC_INLINE constexpr word inplace_binop(Function op_with_carry,
138
cpp::array<word, N> &dst,
139
const cpp::array<word, M> &rhs) {
140
static_assert(N >= M);
141
word carry_out = 0;
142
for (size_t i = 0; i < N; ++i) {
143
const bool has_rhs_value = i < M;
144
const word rhs_value = has_rhs_value ? rhs[i] : 0;
145
const word carry_in = carry_out;
146
dst[i] = op_with_carry(dst[i], rhs_value, carry_in, carry_out);
147
// stop early when rhs is over and no carry is to be propagated.
148
if (!has_rhs_value && carry_out == 0)
149
break;
150
}
151
return carry_out;
152
}
153
154
// In-place addition. Returns carry.
155
template <typename word, size_t N, size_t M>
156
LIBC_INLINE constexpr word add_with_carry(cpp::array<word, N> &dst,
157
const cpp::array<word, M> &rhs) {
158
return inplace_binop(LIBC_NAMESPACE::add_with_carry<word>, dst, rhs);
159
}
160
161
// In-place subtraction. Returns borrow.
162
template <typename word, size_t N, size_t M>
163
LIBC_INLINE constexpr word sub_with_borrow(cpp::array<word, N> &dst,
164
const cpp::array<word, M> &rhs) {
165
return inplace_binop(LIBC_NAMESPACE::sub_with_borrow<word>, dst, rhs);
166
}
167
168
// In-place multiply-add. Returns carry.
169
// i.e., 'dst += b * c'
170
template <typename word, size_t N>
171
LIBC_INLINE constexpr word mul_add_with_carry(cpp::array<word, N> &dst, word b,
172
word c) {
173
return add_with_carry(dst, mul2(b, c));
174
}
175
176
// An array of two elements serving as an accumulator during multiword
177
// computations.
178
template <typename T> struct Accumulator final : cpp::array<T, 2> {
179
using UP = cpp::array<T, 2>;
180
LIBC_INLINE constexpr Accumulator() : UP({0, 0}) {}
181
LIBC_INLINE constexpr T advance(T carry_in) {
182
auto result = UP::front();
183
UP::front() = UP::back();
184
UP::back() = carry_in;
185
return result;
186
}
187
LIBC_INLINE constexpr T sum() const { return UP::front(); }
188
LIBC_INLINE constexpr T carry() const { return UP::back(); }
189
};
190
191
// In-place multiplication by a single word. Returns carry.
192
template <typename word, size_t N>
193
LIBC_INLINE constexpr word scalar_multiply_with_carry(cpp::array<word, N> &dst,
194
word x) {
195
Accumulator<word> acc;
196
for (auto &val : dst) {
197
const word carry = mul_add_with_carry(acc, val, x);
198
val = acc.advance(carry);
199
}
200
return acc.carry();
201
}
202
203
// Multiplication of 'lhs' by 'rhs' into 'dst'. Returns carry.
204
// This function is safe to use for signed numbers.
205
// https://stackoverflow.com/a/20793834
206
// https://pages.cs.wisc.edu/%7Emarkhill/cs354/Fall2008/beyond354/int.mult.html
207
template <typename word, size_t O, size_t M, size_t N>
208
LIBC_INLINE constexpr word multiply_with_carry(cpp::array<word, O> &dst,
209
const cpp::array<word, M> &lhs,
210
const cpp::array<word, N> &rhs) {
211
static_assert(O >= M + N);
212
Accumulator<word> acc;
213
for (size_t i = 0; i < O; ++i) {
214
const size_t lower_idx = i < N ? 0 : i - N + 1;
215
const size_t upper_idx = i < M ? i : M - 1;
216
word carry = 0;
217
for (size_t j = lower_idx; j <= upper_idx; ++j)
218
carry += mul_add_with_carry(acc, lhs[j], rhs[i - j]);
219
dst[i] = acc.advance(carry);
220
}
221
return acc.carry();
222
}
223
224
template <typename word, size_t N>
225
LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst,
226
const cpp::array<word, N> &lhs,
227
const cpp::array<word, N> &rhs) {
228
Accumulator<word> acc;
229
word carry = 0;
230
// First round of accumulation for those at N - 1 in the full product.
231
for (size_t i = 0; i < N; ++i)
232
carry += mul_add_with_carry(acc, lhs[i], rhs[N - 1 - i]);
233
for (size_t i = N; i < 2 * N - 1; ++i) {
234
acc.advance(carry);
235
carry = 0;
236
for (size_t j = i - N + 1; j < N; ++j)
237
carry += mul_add_with_carry(acc, lhs[j], rhs[i - j]);
238
dst[i - N] = acc.sum();
239
}
240
dst.back() = acc.carry();
241
}
242
243
template <typename word, size_t N>
244
LIBC_INLINE constexpr bool is_negative(const cpp::array<word, N> &array) {
245
using signed_word = cpp::make_signed_t<word>;
246
return cpp::bit_cast<signed_word>(array.back()) < 0;
247
}
248
249
// An enum for the shift function below.
250
enum Direction { LEFT, RIGHT };
251
252
// A bitwise shift on an array of elements.
253
// 'offset' must be less than TOTAL_BITS (i.e., sizeof(word) * CHAR_BIT * N)
254
// otherwise the behavior is undefined.
255
template <Direction direction, bool is_signed, typename word, size_t N>
256
LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
257
size_t offset) {
258
static_assert(direction == LEFT || direction == RIGHT);
259
constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits;
260
#ifdef LIBC_TYPES_HAS_INT128
261
constexpr size_t TOTAL_BITS = N * WORD_BITS;
262
if constexpr (TOTAL_BITS == 128) {
263
using type = cpp::conditional_t<is_signed, __int128_t, __uint128_t>;
264
auto tmp = cpp::bit_cast<type>(array);
265
if constexpr (direction == LEFT)
266
tmp <<= offset;
267
else
268
tmp >>= offset;
269
return cpp::bit_cast<cpp::array<word, N>>(tmp);
270
}
271
#endif
272
if (LIBC_UNLIKELY(offset == 0))
273
return array;
274
const bool is_neg = is_signed && is_negative(array);
275
constexpr auto at = [](size_t index) -> int {
276
// reverse iteration when direction == LEFT.
277
if constexpr (direction == LEFT)
278
return int(N) - int(index) - 1;
279
return int(index);
280
};
281
const auto safe_get_at = [&](size_t index) -> word {
282
// return appropriate value when accessing out of bound elements.
283
const int i = at(index);
284
if (i < 0)
285
return 0;
286
if (i >= int(N))
287
return is_neg ? cpp::numeric_limits<word>::max() : 0;
288
return array[static_cast<unsigned>(i)];
289
};
290
const size_t index_offset = offset / WORD_BITS;
291
const size_t bit_offset = offset % WORD_BITS;
292
#ifdef LIBC_COMPILER_IS_CLANG
293
__builtin_assume(index_offset < N);
294
#endif
295
cpp::array<word, N> out = {};
296
for (size_t index = 0; index < N; ++index) {
297
const word part1 = safe_get_at(index + index_offset);
298
const word part2 = safe_get_at(index + index_offset + 1);
299
word &dst = out[static_cast<unsigned>(at(index))];
300
if (bit_offset == 0)
301
dst = part1; // no crosstalk between parts.
302
else if constexpr (direction == LEFT)
303
dst = static_cast<word>((part1 << bit_offset) |
304
(part2 >> (WORD_BITS - bit_offset)));
305
else
306
dst = static_cast<word>((part1 >> bit_offset) |
307
(part2 << (WORD_BITS - bit_offset)));
308
}
309
return out;
310
}
311
312
#define DECLARE_COUNTBIT(NAME, INDEX_EXPR) \
313
template <typename word, size_t N> \
314
LIBC_INLINE constexpr int NAME(const cpp::array<word, N> &val) { \
315
int bit_count = 0; \
316
for (size_t i = 0; i < N; ++i) { \
317
const int word_count = cpp::NAME<word>(val[INDEX_EXPR]); \
318
bit_count += word_count; \
319
if (word_count != cpp::numeric_limits<word>::digits) \
320
break; \
321
} \
322
return bit_count; \
323
}
324
325
DECLARE_COUNTBIT(countr_zero, i) // iterating forward
326
DECLARE_COUNTBIT(countr_one, i) // iterating forward
327
DECLARE_COUNTBIT(countl_zero, N - i - 1) // iterating backward
328
DECLARE_COUNTBIT(countl_one, N - i - 1) // iterating backward
329
330
} // namespace multiword
331
332
template <size_t Bits, bool Signed, typename WordType = uint64_t>
333
struct BigInt {
334
private:
335
static_assert(cpp::is_integral_v<WordType> && cpp::is_unsigned_v<WordType>,
336
"WordType must be unsigned integer.");
337
338
struct Division {
339
BigInt quotient;
340
BigInt remainder;
341
};
342
343
public:
344
using word_type = WordType;
345
using unsigned_type = BigInt<Bits, false, word_type>;
346
using signed_type = BigInt<Bits, true, word_type>;
347
348
LIBC_INLINE_VAR static constexpr bool SIGNED = Signed;
349
LIBC_INLINE_VAR static constexpr size_t BITS = Bits;
350
LIBC_INLINE_VAR
351
static constexpr size_t WORD_SIZE = sizeof(WordType) * CHAR_BIT;
352
353
static_assert(Bits > 0 && Bits % WORD_SIZE == 0,
354
"Number of bits in BigInt should be a multiple of WORD_SIZE.");
355
356
LIBC_INLINE_VAR static constexpr size_t WORD_COUNT = Bits / WORD_SIZE;
357
358
cpp::array<WordType, WORD_COUNT> val{}; // zero initialized.
359
360
LIBC_INLINE constexpr BigInt() = default;
361
362
LIBC_INLINE constexpr BigInt(const BigInt &other) = default;
363
364
template <size_t OtherBits, bool OtherSigned, typename OtherWordType>
365
LIBC_INLINE constexpr BigInt(
366
const BigInt<OtherBits, OtherSigned, OtherWordType> &other) {
367
using BigIntOther = BigInt<OtherBits, OtherSigned, OtherWordType>;
368
const bool should_sign_extend = Signed && other.is_neg();
369
370
static_assert(!(Bits == OtherBits && WORD_SIZE != BigIntOther::WORD_SIZE) &&
371
"This is currently untested for casting between bigints with "
372
"the same bit width but different word sizes.");
373
374
if constexpr (BigIntOther::WORD_SIZE < WORD_SIZE) {
375
// OtherWordType is smaller
376
constexpr size_t WORD_SIZE_RATIO = WORD_SIZE / BigIntOther::WORD_SIZE;
377
static_assert(
378
(WORD_SIZE % BigIntOther::WORD_SIZE) == 0 &&
379
"Word types must be multiples of each other for correct conversion.");
380
if constexpr (OtherBits >= Bits) { // truncate
381
// for each big word
382
for (size_t i = 0; i < WORD_COUNT; ++i) {
383
WordType cur_word = 0;
384
// combine WORD_SIZE_RATIO small words into a big word
385
for (size_t j = 0; j < WORD_SIZE_RATIO; ++j)
386
cur_word |= static_cast<WordType>(other[(i * WORD_SIZE_RATIO) + j])
387
<< (BigIntOther::WORD_SIZE * j);
388
389
val[i] = cur_word;
390
}
391
} else { // zero or sign extend
392
size_t i = 0;
393
WordType cur_word = 0;
394
// for each small word
395
for (; i < BigIntOther::WORD_COUNT; ++i) {
396
// combine WORD_SIZE_RATIO small words into a big word
397
cur_word |= static_cast<WordType>(other[i])
398
<< (BigIntOther::WORD_SIZE * (i % WORD_SIZE_RATIO));
399
// if we've completed a big word, copy it into place and reset
400
if ((i % WORD_SIZE_RATIO) == WORD_SIZE_RATIO - 1) {
401
val[i / WORD_SIZE_RATIO] = cur_word;
402
cur_word = 0;
403
}
404
}
405
// Pretend there are extra words of the correct sign extension as needed
406
407
const WordType extension_bits =
408
should_sign_extend ? cpp::numeric_limits<WordType>::max()
409
: cpp::numeric_limits<WordType>::min();
410
if ((i % WORD_SIZE_RATIO) != 0) {
411
cur_word |= static_cast<WordType>(extension_bits)
412
<< (BigIntOther::WORD_SIZE * (i % WORD_SIZE_RATIO));
413
}
414
// Copy the last word into place.
415
val[(i / WORD_SIZE_RATIO)] = cur_word;
416
extend((i / WORD_SIZE_RATIO) + 1, should_sign_extend);
417
}
418
} else if constexpr (BigIntOther::WORD_SIZE == WORD_SIZE) {
419
if constexpr (OtherBits >= Bits) { // truncate
420
for (size_t i = 0; i < WORD_COUNT; ++i)
421
val[i] = other[i];
422
} else { // zero or sign extend
423
size_t i = 0;
424
for (; i < BigIntOther::WORD_COUNT; ++i)
425
val[i] = other[i];
426
extend(i, should_sign_extend);
427
}
428
} else {
429
// OtherWordType is bigger.
430
constexpr size_t WORD_SIZE_RATIO = BigIntOther::WORD_SIZE / WORD_SIZE;
431
static_assert(
432
(BigIntOther::WORD_SIZE % WORD_SIZE) == 0 &&
433
"Word types must be multiples of each other for correct conversion.");
434
if constexpr (OtherBits >= Bits) { // truncate
435
// for each small word
436
for (size_t i = 0; i < WORD_COUNT; ++i) {
437
// split each big word into WORD_SIZE_RATIO small words
438
val[i] = static_cast<WordType>(other[i / WORD_SIZE_RATIO] >>
439
((i % WORD_SIZE_RATIO) * WORD_SIZE));
440
}
441
} else { // zero or sign extend
442
size_t i = 0;
443
// for each big word
444
for (; i < BigIntOther::WORD_COUNT; ++i) {
445
// split each big word into WORD_SIZE_RATIO small words
446
for (size_t j = 0; j < WORD_SIZE_RATIO; ++j)
447
val[(i * WORD_SIZE_RATIO) + j] =
448
static_cast<WordType>(other[i] >> (j * WORD_SIZE));
449
}
450
extend(i * WORD_SIZE_RATIO, should_sign_extend);
451
}
452
}
453
}
454
455
// Construct a BigInt from a C array.
456
template <size_t N> LIBC_INLINE constexpr BigInt(const WordType (&nums)[N]) {
457
static_assert(N == WORD_COUNT);
458
for (size_t i = 0; i < WORD_COUNT; ++i)
459
val[i] = nums[i];
460
}
461
462
LIBC_INLINE constexpr explicit BigInt(
463
const cpp::array<WordType, WORD_COUNT> &words) {
464
val = words;
465
}
466
467
// Initialize the first word to |v| and the rest to 0.
468
template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T>>>
469
LIBC_INLINE constexpr BigInt(T v) {
470
constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;
471
const bool is_neg = v < 0;
472
for (size_t i = 0; i < WORD_COUNT; ++i) {
473
if (v == 0) {
474
extend(i, is_neg);
475
return;
476
}
477
val[i] = static_cast<WordType>(v);
478
if constexpr (T_SIZE > WORD_SIZE)
479
v >>= WORD_SIZE;
480
else
481
v = 0;
482
}
483
}
484
LIBC_INLINE constexpr BigInt &operator=(const BigInt &other) = default;
485
486
// constants
487
LIBC_INLINE static constexpr BigInt zero() { return BigInt(); }
488
LIBC_INLINE static constexpr BigInt one() { return BigInt(1); }
489
LIBC_INLINE static constexpr BigInt all_ones() { return ~zero(); }
490
LIBC_INLINE static constexpr BigInt min() {
491
BigInt out;
492
if constexpr (SIGNED)
493
out.set_msb();
494
return out;
495
}
496
LIBC_INLINE static constexpr BigInt max() {
497
BigInt out = all_ones();
498
if constexpr (SIGNED)
499
out.clear_msb();
500
return out;
501
}
502
503
// TODO: Reuse the Sign type.
504
LIBC_INLINE constexpr bool is_neg() const { return SIGNED && get_msb(); }
505
506
template <size_t OtherBits, bool OtherSigned, typename OtherWordType>
507
LIBC_INLINE constexpr explicit
508
operator BigInt<OtherBits, OtherSigned, OtherWordType>() const {
509
return BigInt<OtherBits, OtherSigned, OtherWordType>(this);
510
}
511
512
template <typename T> LIBC_INLINE constexpr explicit operator T() const {
513
return to<T>();
514
}
515
516
template <typename T>
517
LIBC_INLINE constexpr cpp::enable_if_t<
518
cpp::is_integral_v<T> && !cpp::is_same_v<T, bool>, T>
519
to() const {
520
constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;
521
T lo = static_cast<T>(val[0]);
522
if constexpr (T_SIZE <= WORD_SIZE)
523
return lo;
524
constexpr size_t MAX_COUNT =
525
T_SIZE > Bits ? WORD_COUNT : T_SIZE / WORD_SIZE;
526
for (size_t i = 1; i < MAX_COUNT; ++i)
527
lo += static_cast<T>(static_cast<T>(val[i]) << (WORD_SIZE * i));
528
if constexpr (Signed && (T_SIZE > Bits)) {
529
// Extend sign for negative numbers.
530
constexpr T MASK = (~T(0) << Bits);
531
if (is_neg())
532
lo |= MASK;
533
}
534
return lo;
535
}
536
537
LIBC_INLINE constexpr explicit operator bool() const { return !is_zero(); }
538
539
LIBC_INLINE constexpr bool is_zero() const {
540
for (auto part : val)
541
if (part != 0)
542
return false;
543
return true;
544
}
545
546
// Add 'rhs' to this number and store the result in this number.
547
// Returns the carry value produced by the addition operation.
548
LIBC_INLINE constexpr WordType add_overflow(const BigInt &rhs) {
549
return multiword::add_with_carry(val, rhs.val);
550
}
551
552
LIBC_INLINE constexpr BigInt operator+(const BigInt &other) const {
553
BigInt result = *this;
554
result.add_overflow(other);
555
return result;
556
}
557
558
// This will only apply when initializing a variable from constant values, so
559
// it will always use the constexpr version of add_with_carry.
560
LIBC_INLINE constexpr BigInt operator+(BigInt &&other) const {
561
// We use addition commutativity to reuse 'other' and prevent allocation.
562
other.add_overflow(*this); // Returned carry value is ignored.
563
return other;
564
}
565
566
LIBC_INLINE constexpr BigInt &operator+=(const BigInt &other) {
567
add_overflow(other); // Returned carry value is ignored.
568
return *this;
569
}
570
571
// Subtract 'rhs' to this number and store the result in this number.
572
// Returns the carry value produced by the subtraction operation.
573
LIBC_INLINE constexpr WordType sub_overflow(const BigInt &rhs) {
574
return multiword::sub_with_borrow(val, rhs.val);
575
}
576
577
LIBC_INLINE constexpr BigInt operator-(const BigInt &other) const {
578
BigInt result = *this;
579
result.sub_overflow(other); // Returned carry value is ignored.
580
return result;
581
}
582
583
LIBC_INLINE constexpr BigInt operator-(BigInt &&other) const {
584
BigInt result = *this;
585
result.sub_overflow(other); // Returned carry value is ignored.
586
return result;
587
}
588
589
LIBC_INLINE constexpr BigInt &operator-=(const BigInt &other) {
590
// TODO(lntue): Set overflow flag / errno when carry is true.
591
sub_overflow(other); // Returned carry value is ignored.
592
return *this;
593
}
594
595
// Multiply this number with x and store the result in this number.
596
LIBC_INLINE constexpr WordType mul(WordType x) {
597
return multiword::scalar_multiply_with_carry(val, x);
598
}
599
600
// Return the full product.
601
template <size_t OtherBits>
602
LIBC_INLINE constexpr auto
603
ful_mul(const BigInt<OtherBits, Signed, WordType> &other) const {
604
BigInt<Bits + OtherBits, Signed, WordType> result;
605
multiword::multiply_with_carry(result.val, val, other.val);
606
return result;
607
}
608
609
LIBC_INLINE constexpr BigInt operator*(const BigInt &other) const {
610
// Perform full mul and truncate.
611
return BigInt(ful_mul(other));
612
}
613
614
// Fast hi part of the full product. The normal product `operator*` returns
615
// `Bits` least significant bits of the full product, while this function will
616
// approximate `Bits` most significant bits of the full product with errors
617
// bounded by:
618
// 0 <= (a.full_mul(b) >> Bits) - a.quick_mul_hi(b)) <= WORD_COUNT - 1.
619
//
620
// An example usage of this is to quickly (but less accurately) compute the
621
// product of (normalized) mantissas of floating point numbers:
622
// (mant_1, mant_2) -> quick_mul_hi -> normalize leading bit
623
// is much more efficient than:
624
// (mant_1, mant_2) -> ful_mul -> normalize leading bit
625
// -> convert back to same Bits width by shifting/rounding,
626
// especially for higher precisions.
627
//
628
// Performance summary:
629
// Number of 64-bit x 64-bit -> 128-bit multiplications performed.
630
// Bits WORD_COUNT ful_mul quick_mul_hi Error bound
631
// 128 2 4 3 1
632
// 196 3 9 6 2
633
// 256 4 16 10 3
634
// 512 8 64 36 7
635
LIBC_INLINE constexpr BigInt quick_mul_hi(const BigInt &other) const {
636
BigInt result;
637
multiword::quick_mul_hi(result.val, val, other.val);
638
return result;
639
}
640
641
// BigInt(x).pow_n(n) computes x ^ n.
642
// Note 0 ^ 0 == 1.
643
LIBC_INLINE constexpr void pow_n(uint64_t power) {
644
static_assert(!Signed);
645
BigInt result = one();
646
BigInt cur_power = *this;
647
while (power > 0) {
648
if ((power % 2) > 0)
649
result *= cur_power;
650
power >>= 1;
651
cur_power *= cur_power;
652
}
653
*this = result;
654
}
655
656
// Performs inplace signed / unsigned division. Returns remainder if not
657
// dividing by zero.
658
// For signed numbers it behaves like C++ signed integer division.
659
// That is by truncating the fractionnal part
660
// https://stackoverflow.com/a/3602857
661
LIBC_INLINE constexpr cpp::optional<BigInt> div(const BigInt &divider) {
662
if (LIBC_UNLIKELY(divider.is_zero()))
663
return cpp::nullopt;
664
if (LIBC_UNLIKELY(divider == BigInt::one()))
665
return BigInt::zero();
666
Division result;
667
if constexpr (SIGNED)
668
result = divide_signed(*this, divider);
669
else
670
result = divide_unsigned(*this, divider);
671
*this = result.quotient;
672
return result.remainder;
673
}
674
675
// Efficiently perform BigInt / (x * 2^e), where x is a half-word-size
676
// unsigned integer, and return the remainder. The main idea is as follow:
677
// Let q = y / (x * 2^e) be the quotient, and
678
// r = y % (x * 2^e) be the remainder.
679
// First, notice that:
680
// r % (2^e) = y % (2^e),
681
// so we just need to focus on all the bits of y that is >= 2^e.
682
// To speed up the shift-and-add steps, we only use x as the divisor, and
683
// performing 32-bit shiftings instead of bit-by-bit shiftings.
684
// Since the remainder of each division step < x < 2^(WORD_SIZE / 2), the
685
// computation of each step is now properly contained within WordType.
686
// And finally we perform some extra alignment steps for the remaining bits.
687
LIBC_INLINE constexpr cpp::optional<BigInt>
688
div_uint_half_times_pow_2(multiword::half_width_t<WordType> x, size_t e) {
689
BigInt remainder;
690
if (x == 0)
691
return cpp::nullopt;
692
if (e >= Bits) {
693
remainder = *this;
694
*this = BigInt<Bits, false, WordType>();
695
return remainder;
696
}
697
BigInt quotient;
698
WordType x_word = static_cast<WordType>(x);
699
constexpr size_t LOG2_WORD_SIZE =
700
static_cast<size_t>(cpp::bit_width(WORD_SIZE) - 1);
701
constexpr size_t HALF_WORD_SIZE = WORD_SIZE >> 1;
702
constexpr WordType HALF_MASK = ((WordType(1) << HALF_WORD_SIZE) - 1);
703
// lower = smallest multiple of WORD_SIZE that is >= e.
704
size_t lower = ((e >> LOG2_WORD_SIZE) + ((e & (WORD_SIZE - 1)) != 0))
705
<< LOG2_WORD_SIZE;
706
// lower_pos is the index of the closest WORD_SIZE-bit chunk >= 2^e.
707
size_t lower_pos = lower / WORD_SIZE;
708
// Keep track of current remainder mod x * 2^(32*i)
709
WordType rem = 0;
710
// pos is the index of the current 64-bit chunk that we are processing.
711
size_t pos = WORD_COUNT;
712
713
// TODO: look into if constexpr(Bits > 256) skip leading zeroes.
714
715
for (size_t q_pos = WORD_COUNT - lower_pos; q_pos > 0; --q_pos) {
716
// q_pos is 1 + the index of the current WORD_SIZE-bit chunk of the
717
// quotient being processed. Performing the division / modulus with
718
// divisor:
719
// x * 2^(WORD_SIZE*q_pos - WORD_SIZE/2),
720
// i.e. using the upper (WORD_SIZE/2)-bit of the current WORD_SIZE-bit
721
// chunk.
722
rem <<= HALF_WORD_SIZE;
723
rem += val[--pos] >> HALF_WORD_SIZE;
724
WordType q_tmp = rem / x_word;
725
rem %= x_word;
726
727
// Performing the division / modulus with divisor:
728
// x * 2^(WORD_SIZE*(q_pos - 1)),
729
// i.e. using the lower (WORD_SIZE/2)-bit of the current WORD_SIZE-bit
730
// chunk.
731
rem <<= HALF_WORD_SIZE;
732
rem += val[pos] & HALF_MASK;
733
quotient.val[q_pos - 1] = (q_tmp << HALF_WORD_SIZE) + rem / x_word;
734
rem %= x_word;
735
}
736
737
// So far, what we have is:
738
// quotient = y / (x * 2^lower), and
739
// rem = (y % (x * 2^lower)) / 2^lower.
740
// If (lower > e), we will need to perform an extra adjustment of the
741
// quotient and remainder, namely:
742
// y / (x * 2^e) = [ y / (x * 2^lower) ] * 2^(lower - e) +
743
// + (rem * 2^(lower - e)) / x
744
// (y % (x * 2^e)) / 2^e = (rem * 2^(lower - e)) % x
745
size_t last_shift = lower - e;
746
747
if (last_shift > 0) {
748
// quotient * 2^(lower - e)
749
quotient <<= last_shift;
750
WordType q_tmp = 0;
751
WordType d = val[--pos];
752
if (last_shift >= HALF_WORD_SIZE) {
753
// The shifting (rem * 2^(lower - e)) might overflow WordTyoe, so we
754
// perform a HALF_WORD_SIZE-bit shift first.
755
rem <<= HALF_WORD_SIZE;
756
rem += d >> HALF_WORD_SIZE;
757
d &= HALF_MASK;
758
q_tmp = rem / x_word;
759
rem %= x_word;
760
last_shift -= HALF_WORD_SIZE;
761
} else {
762
// Only use the upper HALF_WORD_SIZE-bit of the current WORD_SIZE-bit
763
// chunk.
764
d >>= HALF_WORD_SIZE;
765
}
766
767
if (last_shift > 0) {
768
rem <<= HALF_WORD_SIZE;
769
rem += d;
770
q_tmp <<= last_shift;
771
x_word <<= HALF_WORD_SIZE - last_shift;
772
q_tmp += rem / x_word;
773
rem %= x_word;
774
}
775
776
quotient.val[0] += q_tmp;
777
778
if (lower - e <= HALF_WORD_SIZE) {
779
// The remainder rem * 2^(lower - e) might overflow to the higher
780
// WORD_SIZE-bit chunk.
781
if (pos < WORD_COUNT - 1) {
782
remainder[pos + 1] = rem >> HALF_WORD_SIZE;
783
}
784
remainder[pos] = (rem << HALF_WORD_SIZE) + (val[pos] & HALF_MASK);
785
} else {
786
remainder[pos] = rem;
787
}
788
789
} else {
790
remainder[pos] = rem;
791
}
792
793
// Set the remaining lower bits of the remainder.
794
for (; pos > 0; --pos) {
795
remainder[pos - 1] = val[pos - 1];
796
}
797
798
*this = quotient;
799
return remainder;
800
}
801
802
LIBC_INLINE constexpr BigInt operator/(const BigInt &other) const {
803
BigInt result(*this);
804
result.div(other);
805
return result;
806
}
807
808
LIBC_INLINE constexpr BigInt &operator/=(const BigInt &other) {
809
div(other);
810
return *this;
811
}
812
813
LIBC_INLINE constexpr BigInt operator%(const BigInt &other) const {
814
BigInt result(*this);
815
return *result.div(other);
816
}
817
818
LIBC_INLINE constexpr BigInt operator%=(const BigInt &other) {
819
*this = *this % other;
820
return *this;
821
}
822
823
LIBC_INLINE constexpr BigInt &operator*=(const BigInt &other) {
824
*this = *this * other;
825
return *this;
826
}
827
828
LIBC_INLINE constexpr BigInt &operator<<=(size_t s) {
829
val = multiword::shift<multiword::LEFT, SIGNED>(val, s);
830
return *this;
831
}
832
833
LIBC_INLINE constexpr BigInt operator<<(size_t s) const {
834
return BigInt(multiword::shift<multiword::LEFT, SIGNED>(val, s));
835
}
836
837
LIBC_INLINE constexpr BigInt &operator>>=(size_t s) {
838
val = multiword::shift<multiword::RIGHT, SIGNED>(val, s);
839
return *this;
840
}
841
842
LIBC_INLINE constexpr BigInt operator>>(size_t s) const {
843
return BigInt(multiword::shift<multiword::RIGHT, SIGNED>(val, s));
844
}
845
846
#define DEFINE_BINOP(OP) \
847
LIBC_INLINE friend constexpr BigInt operator OP(const BigInt &lhs, \
848
const BigInt &rhs) { \
849
BigInt result; \
850
for (size_t i = 0; i < WORD_COUNT; ++i) \
851
result[i] = lhs[i] OP rhs[i]; \
852
return result; \
853
} \
854
LIBC_INLINE friend constexpr BigInt operator OP##=(BigInt &lhs, \
855
const BigInt &rhs) { \
856
for (size_t i = 0; i < WORD_COUNT; ++i) \
857
lhs[i] OP## = rhs[i]; \
858
return lhs; \
859
}
860
861
DEFINE_BINOP(&) // & and &=
862
DEFINE_BINOP(|) // | and |=
863
DEFINE_BINOP(^) // ^ and ^=
864
#undef DEFINE_BINOP
865
866
LIBC_INLINE constexpr BigInt operator~() const {
867
BigInt result;
868
for (size_t i = 0; i < WORD_COUNT; ++i)
869
result[i] = static_cast<WordType>(~val[i]);
870
return result;
871
}
872
873
LIBC_INLINE constexpr BigInt operator-() const {
874
BigInt result(*this);
875
result.negate();
876
return result;
877
}
878
879
LIBC_INLINE friend constexpr bool operator==(const BigInt &lhs,
880
const BigInt &rhs) {
881
for (size_t i = 0; i < WORD_COUNT; ++i)
882
if (lhs.val[i] != rhs.val[i])
883
return false;
884
return true;
885
}
886
887
LIBC_INLINE friend constexpr bool operator!=(const BigInt &lhs,
888
const BigInt &rhs) {
889
return !(lhs == rhs);
890
}
891
892
LIBC_INLINE friend constexpr bool operator>(const BigInt &lhs,
893
const BigInt &rhs) {
894
return cmp(lhs, rhs) > 0;
895
}
896
LIBC_INLINE friend constexpr bool operator>=(const BigInt &lhs,
897
const BigInt &rhs) {
898
return cmp(lhs, rhs) >= 0;
899
}
900
LIBC_INLINE friend constexpr bool operator<(const BigInt &lhs,
901
const BigInt &rhs) {
902
return cmp(lhs, rhs) < 0;
903
}
904
LIBC_INLINE friend constexpr bool operator<=(const BigInt &lhs,
905
const BigInt &rhs) {
906
return cmp(lhs, rhs) <= 0;
907
}
908
909
LIBC_INLINE constexpr BigInt &operator++() {
910
increment();
911
return *this;
912
}
913
914
LIBC_INLINE constexpr BigInt operator++(int) {
915
BigInt oldval(*this);
916
increment();
917
return oldval;
918
}
919
920
LIBC_INLINE constexpr BigInt &operator--() {
921
decrement();
922
return *this;
923
}
924
925
LIBC_INLINE constexpr BigInt operator--(int) {
926
BigInt oldval(*this);
927
decrement();
928
return oldval;
929
}
930
931
// Return the i-th word of the number.
932
LIBC_INLINE constexpr const WordType &operator[](size_t i) const {
933
return val[i];
934
}
935
936
// Return the i-th word of the number.
937
LIBC_INLINE constexpr WordType &operator[](size_t i) { return val[i]; }
938
939
// Return the i-th bit of the number.
940
LIBC_INLINE constexpr bool get_bit(size_t i) const {
941
const size_t word_index = i / WORD_SIZE;
942
return 1 & (val[word_index] >> (i % WORD_SIZE));
943
}
944
945
// Set the i-th bit of the number.
946
LIBC_INLINE constexpr void set_bit(size_t i) {
947
const size_t word_index = i / WORD_SIZE;
948
val[word_index] |= WordType(1) << (i % WORD_SIZE);
949
}
950
951
private:
952
LIBC_INLINE friend constexpr int cmp(const BigInt &lhs, const BigInt &rhs) {
953
constexpr auto compare = [](WordType a, WordType b) {
954
return a == b ? 0 : a > b ? 1 : -1;
955
};
956
if constexpr (Signed) {
957
const bool lhs_is_neg = lhs.is_neg();
958
const bool rhs_is_neg = rhs.is_neg();
959
if (lhs_is_neg != rhs_is_neg)
960
return rhs_is_neg ? 1 : -1;
961
}
962
for (size_t i = WORD_COUNT; i-- > 0;)
963
if (auto cmp = compare(lhs[i], rhs[i]); cmp != 0)
964
return cmp;
965
return 0;
966
}
967
968
LIBC_INLINE constexpr void bitwise_not() {
969
for (auto &part : val)
970
part = static_cast<WordType>(~part);
971
}
972
973
LIBC_INLINE constexpr void negate() {
974
bitwise_not();
975
increment();
976
}
977
978
LIBC_INLINE constexpr void increment() {
979
multiword::add_with_carry(val, cpp::array<WordType, 1>{1});
980
}
981
982
LIBC_INLINE constexpr void decrement() {
983
multiword::sub_with_borrow(val, cpp::array<WordType, 1>{1});
984
}
985
986
LIBC_INLINE constexpr void extend(size_t index, bool is_neg) {
987
const WordType value = is_neg ? cpp::numeric_limits<WordType>::max()
988
: cpp::numeric_limits<WordType>::min();
989
for (size_t i = index; i < WORD_COUNT; ++i)
990
val[i] = value;
991
}
992
993
LIBC_INLINE constexpr bool get_msb() const {
994
return val.back() >> (WORD_SIZE - 1);
995
}
996
997
LIBC_INLINE constexpr void set_msb() {
998
val.back() |= mask_leading_ones<WordType, 1>();
999
}
1000
1001
LIBC_INLINE constexpr void clear_msb() {
1002
val.back() &= mask_trailing_ones<WordType, WORD_SIZE - 1>();
1003
}
1004
LIBC_INLINE constexpr static Division divide_unsigned(const BigInt &dividend,
1005
const BigInt &divider) {
1006
BigInt remainder = dividend;
1007
BigInt quotient;
1008
if (remainder >= divider) {
1009
BigInt subtractor = divider;
1010
int cur_bit = multiword::countl_zero(subtractor.val) -
1011
multiword::countl_zero(remainder.val);
1012
subtractor <<= static_cast<size_t>(cur_bit);
1013
for (; cur_bit >= 0 && remainder > 0; --cur_bit, subtractor >>= 1) {
1014
if (remainder < subtractor)
1015
continue;
1016
remainder -= subtractor;
1017
quotient.set_bit(static_cast<size_t>(cur_bit));
1018
}
1019
}
1020
return Division{quotient, remainder};
1021
}
1022
1023
LIBC_INLINE constexpr static Division divide_signed(const BigInt &dividend,
1024
const BigInt &divider) {
1025
// Special case because it is not possible to negate the min value of a
1026
// signed integer.
1027
if (dividend == min() && divider == min())
1028
return Division{one(), zero()};
1029
// 1. Convert the dividend and divisor to unsigned representation.
1030
unsigned_type udividend(dividend);
1031
unsigned_type udivider(divider);
1032
// 2. Negate the dividend if it's negative, and similarly for the divisor.
1033
const bool dividend_is_neg = dividend.is_neg();
1034
const bool divider_is_neg = divider.is_neg();
1035
if (dividend_is_neg)
1036
udividend.negate();
1037
if (divider_is_neg)
1038
udivider.negate();
1039
// 3. Use unsigned multiword division algorithm.
1040
const auto unsigned_result = divide_unsigned(udividend, udivider);
1041
// 4. Convert the quotient and remainder to signed representation.
1042
Division result;
1043
result.quotient = signed_type(unsigned_result.quotient);
1044
result.remainder = signed_type(unsigned_result.remainder);
1045
// 5. Negate the quotient if the dividend and divisor had opposite signs.
1046
if (dividend_is_neg != divider_is_neg)
1047
result.quotient.negate();
1048
// 6. Negate the remainder if the dividend was negative.
1049
if (dividend_is_neg)
1050
result.remainder.negate();
1051
return result;
1052
}
1053
1054
friend signed_type;
1055
friend unsigned_type;
1056
};
1057
1058
namespace internal {
1059
// We default BigInt's WordType to 'uint64_t' or 'uint32_t' depending on type
1060
// availability.
1061
template <size_t Bits>
1062
struct WordTypeSelector : cpp::type_identity<
1063
#ifdef LIBC_TYPES_HAS_INT64
1064
uint64_t
1065
#else
1066
uint32_t
1067
#endif // LIBC_TYPES_HAS_INT64
1068
> {
1069
};
1070
// Except if we request 16 or 32 bits explicitly.
1071
template <> struct WordTypeSelector<16> : cpp::type_identity<uint16_t> {};
1072
template <> struct WordTypeSelector<32> : cpp::type_identity<uint32_t> {};
1073
template <> struct WordTypeSelector<96> : cpp::type_identity<uint32_t> {};
1074
1075
template <size_t Bits>
1076
using WordTypeSelectorT = typename WordTypeSelector<Bits>::type;
1077
} // namespace internal
1078
1079
template <size_t Bits>
1080
using UInt = BigInt<Bits, false, internal::WordTypeSelectorT<Bits>>;
1081
1082
template <size_t Bits>
1083
using Int = BigInt<Bits, true, internal::WordTypeSelectorT<Bits>>;
1084
1085
// Provides limits of BigInt.
1086
template <size_t Bits, bool Signed, typename T>
1087
struct cpp::numeric_limits<BigInt<Bits, Signed, T>> {
1088
LIBC_INLINE static constexpr BigInt<Bits, Signed, T> max() {
1089
return BigInt<Bits, Signed, T>::max();
1090
}
1091
LIBC_INLINE static constexpr BigInt<Bits, Signed, T> min() {
1092
return BigInt<Bits, Signed, T>::min();
1093
}
1094
// Meant to match std::numeric_limits interface.
1095
// NOLINTNEXTLINE(readability-identifier-naming)
1096
LIBC_INLINE_VAR static constexpr int digits = Bits - Signed;
1097
};
1098
1099
// type traits to determine whether a T is a BigInt.
1100
template <typename T> struct is_big_int : cpp::false_type {};
1101
1102
template <size_t Bits, bool Signed, typename T>
1103
struct is_big_int<BigInt<Bits, Signed, T>> : cpp::true_type {};
1104
1105
template <class T>
1106
LIBC_INLINE_VAR constexpr bool is_big_int_v = is_big_int<T>::value;
1107
1108
// extensions of type traits to include BigInt
1109
1110
// is_integral_or_big_int
1111
template <typename T>
1112
struct is_integral_or_big_int
1113
: cpp::bool_constant<(cpp::is_integral_v<T> || is_big_int_v<T>)> {};
1114
1115
template <typename T>
1116
LIBC_INLINE_VAR constexpr bool is_integral_or_big_int_v =
1117
is_integral_or_big_int<T>::value;
1118
1119
// make_big_int_unsigned
1120
template <typename T> struct make_big_int_unsigned;
1121
1122
template <size_t Bits, bool Signed, typename T>
1123
struct make_big_int_unsigned<BigInt<Bits, Signed, T>>
1124
: cpp::type_identity<BigInt<Bits, false, T>> {};
1125
1126
template <typename T>
1127
using make_big_int_unsigned_t = typename make_big_int_unsigned<T>::type;
1128
1129
// make_big_int_signed
1130
template <typename T> struct make_big_int_signed;
1131
1132
template <size_t Bits, bool Signed, typename T>
1133
struct make_big_int_signed<BigInt<Bits, Signed, T>>
1134
: cpp::type_identity<BigInt<Bits, true, T>> {};
1135
1136
template <typename T>
1137
using make_big_int_signed_t = typename make_big_int_signed<T>::type;
1138
1139
// make_integral_or_big_int_unsigned
1140
template <typename T, class = void> struct make_integral_or_big_int_unsigned;
1141
1142
template <typename T>
1143
struct make_integral_or_big_int_unsigned<
1144
T, cpp::enable_if_t<cpp::is_integral_v<T>>> : cpp::make_unsigned<T> {};
1145
1146
template <typename T>
1147
struct make_integral_or_big_int_unsigned<T, cpp::enable_if_t<is_big_int_v<T>>>
1148
: make_big_int_unsigned<T> {};
1149
1150
template <typename T>
1151
using make_integral_or_big_int_unsigned_t =
1152
typename make_integral_or_big_int_unsigned<T>::type;
1153
1154
// make_integral_or_big_int_signed
1155
template <typename T, class = void> struct make_integral_or_big_int_signed;
1156
1157
template <typename T>
1158
struct make_integral_or_big_int_signed<T,
1159
cpp::enable_if_t<cpp::is_integral_v<T>>>
1160
: cpp::make_signed<T> {};
1161
1162
template <typename T>
1163
struct make_integral_or_big_int_signed<T, cpp::enable_if_t<is_big_int_v<T>>>
1164
: make_big_int_signed<T> {};
1165
1166
template <typename T>
1167
using make_integral_or_big_int_signed_t =
1168
typename make_integral_or_big_int_signed<T>::type;
1169
1170
// is_unsigned_integral_or_big_int
1171
template <typename T>
1172
struct is_unsigned_integral_or_big_int
1173
: cpp::bool_constant<
1174
cpp::is_same_v<T, make_integral_or_big_int_unsigned_t<T>>> {};
1175
1176
template <typename T>
1177
// Meant to look like <type_traits> helper variable templates.
1178
// NOLINTNEXTLINE(readability-identifier-naming)
1179
LIBC_INLINE_VAR constexpr bool is_unsigned_integral_or_big_int_v =
1180
is_unsigned_integral_or_big_int<T>::value;
1181
1182
namespace cpp {
1183
1184
// Specialization of cpp::bit_cast ('bit.h') from T to BigInt.
1185
template <typename To, typename From>
1186
LIBC_INLINE constexpr cpp::enable_if_t<
1187
(sizeof(To) == sizeof(From)) && cpp::is_trivially_copyable<To>::value &&
1188
cpp::is_trivially_copyable<From>::value && is_big_int<To>::value,
1189
To>
1190
bit_cast(const From &from) {
1191
To out;
1192
using Storage = decltype(out.val);
1193
out.val = cpp::bit_cast<Storage>(from);
1194
return out;
1195
}
1196
1197
// Specialization of cpp::bit_cast ('bit.h') from BigInt to T.
1198
template <typename To, size_t Bits>
1199
LIBC_INLINE constexpr cpp::enable_if_t<
1200
sizeof(To) == sizeof(UInt<Bits>) &&
1201
cpp::is_trivially_constructible<To>::value &&
1202
cpp::is_trivially_copyable<To>::value &&
1203
cpp::is_trivially_copyable<UInt<Bits>>::value,
1204
To>
1205
bit_cast(const UInt<Bits> &from) {
1206
return cpp::bit_cast<To>(from.val);
1207
}
1208
1209
// Specialization of cpp::popcount ('bit.h') for BigInt.
1210
template <typename T>
1211
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1212
popcount(T value) {
1213
int bits = 0;
1214
for (auto word : value.val)
1215
if (word)
1216
bits += popcount(word);
1217
return bits;
1218
}
1219
1220
// Specialization of cpp::has_single_bit ('bit.h') for BigInt.
1221
template <typename T>
1222
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, bool>
1223
has_single_bit(T value) {
1224
int bits = 0;
1225
for (auto word : value.val) {
1226
if (word == 0)
1227
continue;
1228
bits += popcount(word);
1229
if (bits > 1)
1230
return false;
1231
}
1232
return bits == 1;
1233
}
1234
1235
// Specialization of cpp::countr_zero ('bit.h') for BigInt.
1236
template <typename T>
1237
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1238
countr_zero(const T &value) {
1239
return multiword::countr_zero(value.val);
1240
}
1241
1242
// Specialization of cpp::countl_zero ('bit.h') for BigInt.
1243
template <typename T>
1244
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1245
countl_zero(const T &value) {
1246
return multiword::countl_zero(value.val);
1247
}
1248
1249
// Specialization of cpp::countl_one ('bit.h') for BigInt.
1250
template <typename T>
1251
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1252
countl_one(T value) {
1253
return multiword::countl_one(value.val);
1254
}
1255
1256
// Specialization of cpp::countr_one ('bit.h') for BigInt.
1257
template <typename T>
1258
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1259
countr_one(T value) {
1260
return multiword::countr_one(value.val);
1261
}
1262
1263
// Specialization of cpp::bit_width ('bit.h') for BigInt.
1264
template <typename T>
1265
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1266
bit_width(T value) {
1267
return cpp::numeric_limits<T>::digits - cpp::countl_zero(value);
1268
}
1269
1270
// Forward-declare rotr so that rotl can use it.
1271
template <typename T>
1272
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
1273
rotr(T value, int rotate);
1274
1275
// Specialization of cpp::rotl ('bit.h') for BigInt.
1276
template <typename T>
1277
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
1278
rotl(T value, int rotate) {
1279
constexpr int N = cpp::numeric_limits<T>::digits;
1280
rotate = rotate % N;
1281
if (!rotate)
1282
return value;
1283
if (rotate < 0)
1284
return cpp::rotr<T>(value, -rotate);
1285
return (value << static_cast<size_t>(rotate)) |
1286
(value >> (N - static_cast<size_t>(rotate)));
1287
}
1288
1289
// Specialization of cpp::rotr ('bit.h') for BigInt.
1290
template <typename T>
1291
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
1292
rotr(T value, int rotate) {
1293
constexpr int N = cpp::numeric_limits<T>::digits;
1294
rotate = rotate % N;
1295
if (!rotate)
1296
return value;
1297
if (rotate < 0)
1298
return cpp::rotl<T>(value, -rotate);
1299
return (value >> static_cast<size_t>(rotate)) |
1300
(value << (N - static_cast<size_t>(rotate)));
1301
}
1302
1303
} // namespace cpp
1304
1305
// Specialization of mask_trailing_ones ('math_extras.h') for BigInt.
1306
template <typename T, size_t count>
1307
LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
1308
mask_trailing_ones() {
1309
static_assert(!T::SIGNED && count <= T::BITS);
1310
if (count == T::BITS)
1311
return T::all_ones();
1312
constexpr size_t QUOTIENT = count / T::WORD_SIZE;
1313
constexpr size_t REMAINDER = count % T::WORD_SIZE;
1314
T out; // zero initialized
1315
for (size_t i = 0; i <= QUOTIENT; ++i)
1316
out[i] = i < QUOTIENT
1317
? cpp::numeric_limits<typename T::word_type>::max()
1318
: mask_trailing_ones<typename T::word_type, REMAINDER>();
1319
return out;
1320
}
1321
1322
// Specialization of mask_leading_ones ('math_extras.h') for BigInt.
1323
template <typename T, size_t count>
1324
LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() {
1325
static_assert(!T::SIGNED && count <= T::BITS);
1326
if (count == T::BITS)
1327
return T::all_ones();
1328
constexpr size_t QUOTIENT = (T::BITS - count - 1U) / T::WORD_SIZE;
1329
constexpr size_t REMAINDER = count % T::WORD_SIZE;
1330
T out; // zero initialized
1331
for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i)
1332
out[i] = i > QUOTIENT
1333
? cpp::numeric_limits<typename T::word_type>::max()
1334
: mask_leading_ones<typename T::word_type, REMAINDER>();
1335
return out;
1336
}
1337
1338
// Specialization of mask_trailing_zeros ('math_extras.h') for BigInt.
1339
template <typename T, size_t count>
1340
LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
1341
mask_trailing_zeros() {
1342
return mask_leading_ones<T, T::BITS - count>();
1343
}
1344
1345
// Specialization of mask_leading_zeros ('math_extras.h') for BigInt.
1346
template <typename T, size_t count>
1347
LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
1348
mask_leading_zeros() {
1349
return mask_trailing_ones<T, T::BITS - count>();
1350
}
1351
1352
// Specialization of count_zeros ('math_extras.h') for BigInt.
1353
template <typename T>
1354
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1355
count_zeros(T value) {
1356
return cpp::popcount(~value);
1357
}
1358
1359
// Specialization of first_leading_zero ('math_extras.h') for BigInt.
1360
template <typename T>
1361
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1362
first_leading_zero(T value) {
1363
return value == cpp::numeric_limits<T>::max() ? 0
1364
: cpp::countl_one(value) + 1;
1365
}
1366
1367
// Specialization of first_leading_one ('math_extras.h') for BigInt.
1368
template <typename T>
1369
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1370
first_leading_one(T value) {
1371
return first_leading_zero(~value);
1372
}
1373
1374
// Specialization of first_trailing_zero ('math_extras.h') for BigInt.
1375
template <typename T>
1376
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1377
first_trailing_zero(T value) {
1378
return value == cpp::numeric_limits<T>::max() ? 0
1379
: cpp::countr_zero(~value) + 1;
1380
}
1381
1382
// Specialization of first_trailing_one ('math_extras.h') for BigInt.
1383
template <typename T>
1384
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1385
first_trailing_one(T value) {
1386
return value == 0 ? 0 : cpp::countr_zero(value) + 1;
1387
}
1388
1389
} // namespace LIBC_NAMESPACE_DECL
1390
1391
#endif // LLVM_LIBC_SRC___SUPPORT_BIG_INT_H
1392
1393