1 //===-- A class to manipulate wide integers. --------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC_SUPPORT_UINT_H
10 #define LLVM_LIBC_SRC_SUPPORT_UINT_H
12 #include "src/__support/CPP/array.h"
13 #include "src/__support/CPP/limits.h"
14 #include "src/__support/CPP/optional.h"
15 #include "src/__support/CPP/type_traits.h"
16 #include "src/__support/builtin_wrappers.h"
17 #include "src/__support/integer_utils.h"
18 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
19 #include "src/__support/number_pair.h"
21 #include <stddef.h> // For size_t
24 namespace __llvm_libc::cpp
{
26 template <size_t Bits
> struct UInt
{
28 static_assert(Bits
> 0 && Bits
% 64 == 0,
29 "Number of bits in UInt should be a multiple of 64.");
30 static constexpr size_t WORDCOUNT
= Bits
/ 64;
31 uint64_t val
[WORDCOUNT
]{};
33 static constexpr uint64_t MASK32
= 0xFFFFFFFFu
;
35 static constexpr uint64_t low(uint64_t v
) { return v
& MASK32
; }
36 static constexpr uint64_t high(uint64_t v
) { return (v
>> 32) & MASK32
; }
38 constexpr UInt() = default;
40 constexpr UInt(const UInt
<Bits
> &other
) = default;
42 template <size_t OtherBits
> constexpr UInt(const UInt
<OtherBits
> &other
) {
43 if (OtherBits
>= Bits
) {
44 for (size_t i
= 0; i
< WORDCOUNT
; ++i
)
48 for (; i
< OtherBits
/ 64; ++i
)
50 for (; i
< WORDCOUNT
; ++i
)
55 // Construct a UInt from a C array.
56 template <size_t N
, enable_if_t
<N
<= WORDCOUNT
, int> = 0>
57 constexpr UInt(const uint64_t (&nums
)[N
]) {
58 size_t min_wordcount
= N
< WORDCOUNT
? N
: WORDCOUNT
;
60 for (; i
< min_wordcount
; ++i
)
63 // If nums doesn't completely fill val, then fill the rest with zeroes.
64 for (; i
< WORDCOUNT
; ++i
)
68 // Initialize the first word to |v| and the rest to 0.
69 constexpr UInt(uint64_t v
) {
71 for (size_t i
= 1; i
< WORDCOUNT
; ++i
) {
75 constexpr explicit UInt(const cpp::array
<uint64_t, WORDCOUNT
> &words
) {
76 for (size_t i
= 0; i
< WORDCOUNT
; ++i
)
80 constexpr explicit operator uint64_t() const { return val
[0]; }
82 constexpr explicit operator uint32_t() const {
83 return uint32_t(uint64_t(*this));
86 constexpr explicit operator uint16_t() const {
87 return uint16_t(uint64_t(*this));
90 constexpr explicit operator uint8_t() const {
91 return uint8_t(uint64_t(*this));
94 constexpr explicit operator bool() const { return !is_zero(); }
96 UInt
<Bits
> &operator=(const UInt
<Bits
> &other
) = default;
98 constexpr bool is_zero() const {
99 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
106 // Add x to this number and store the result in this number.
107 // Returns the carry value produced by the addition operation.
108 constexpr uint64_t add(const UInt
<Bits
> &x
) {
109 SumCarry
<uint64_t> s
{0, 0};
110 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
111 s
= add_with_carry(val
[i
], x
.val
[i
], s
.carry
);
117 UInt
<Bits
> operator+(const UInt
<Bits
> &other
) const {
119 SumCarry
<uint64_t> s
{0, 0};
120 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
121 s
= add_with_carry(val
[i
], other
.val
[i
], s
.carry
);
122 result
.val
[i
] = s
.sum
;
127 // This will only apply when initializing a variable from constant values, so
128 // it will always use the constexpr version of add_with_carry.
129 constexpr UInt
<Bits
> operator+(UInt
<Bits
> &&other
) const {
131 SumCarry
<uint64_t> s
{0, 0};
132 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
133 s
= add_with_carry_const(val
[i
], other
.val
[i
], s
.carry
);
134 result
.val
[i
] = s
.sum
;
139 constexpr UInt
<Bits
> &operator+=(const UInt
<Bits
> &other
) {
140 add(other
); // Returned carry value is ignored.
144 // Subtract x to this number and store the result in this number.
145 // Returns the carry value produced by the subtraction operation.
146 constexpr uint64_t sub(const UInt
<Bits
> &x
) {
147 DiffBorrow
<uint64_t> d
{0, 0};
148 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
149 d
= sub_with_borrow(val
[i
], x
.val
[i
], d
.borrow
);
155 UInt
<Bits
> operator-(const UInt
<Bits
> &other
) const {
157 DiffBorrow
<uint64_t> d
{0, 0};
158 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
159 d
= sub_with_borrow(val
[i
], other
.val
[i
], d
.borrow
);
160 result
.val
[i
] = d
.diff
;
165 constexpr UInt
<Bits
> operator-(UInt
<Bits
> &&other
) const {
167 DiffBorrow
<uint64_t> d
{0, 0};
168 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
169 d
= sub_with_borrow_const(val
[i
], other
.val
[i
], d
.borrow
);
170 result
.val
[i
] = d
.diff
;
175 constexpr UInt
<Bits
> &operator-=(const UInt
<Bits
> &other
) {
176 // TODO(lntue): Set overflow flag / errno when carry is true.
181 // Multiply this number with x and store the result in this number. It is
182 // implemented using the long multiplication algorithm by splitting the
183 // 64-bit words of this number and |x| in to 32-bit halves but peforming
184 // the operations using 64-bit numbers. This ensures that we don't lose the
186 // Returns the carry value produced by the multiplication operation.
187 constexpr uint64_t mul(uint64_t x
) {
188 UInt
<128> partial_sum(0);
190 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
191 NumberPair
<uint64_t> prod
= full_mul(val
[i
], x
);
192 UInt
<128> tmp({prod
.lo
, prod
.hi
});
193 carry
+= partial_sum
.add(tmp
);
194 val
[i
] = partial_sum
.val
[0];
195 partial_sum
.val
[0] = partial_sum
.val
[1];
196 partial_sum
.val
[1] = carry
;
199 return partial_sum
.val
[1];
202 constexpr UInt
<Bits
> operator*(const UInt
<Bits
> &other
) const {
203 if constexpr (WORDCOUNT
== 1) {
204 return {val
[0] * other
.val
[0]};
206 UInt
<Bits
> result(0);
207 UInt
<128> partial_sum(0);
209 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
210 for (size_t j
= 0; j
<= i
; j
++) {
211 NumberPair
<uint64_t> prod
= full_mul(val
[j
], other
.val
[i
- j
]);
212 UInt
<128> tmp({prod
.lo
, prod
.hi
});
213 carry
+= partial_sum
.add(tmp
);
215 result
.val
[i
] = partial_sum
.val
[0];
216 partial_sum
.val
[0] = partial_sum
.val
[1];
217 partial_sum
.val
[1] = carry
;
224 // Return the full product.
225 template <size_t OtherBits
>
226 constexpr UInt
<Bits
+ OtherBits
> ful_mul(const UInt
<OtherBits
> &other
) const {
227 UInt
<Bits
+ OtherBits
> result(0);
228 UInt
<128> partial_sum(0);
230 constexpr size_t OTHER_WORDCOUNT
= UInt
<OtherBits
>::WORDCOUNT
;
231 for (size_t i
= 0; i
<= WORDCOUNT
+ OTHER_WORDCOUNT
- 2; ++i
) {
232 const size_t lower_idx
=
233 i
< OTHER_WORDCOUNT
? 0 : i
- OTHER_WORDCOUNT
+ 1;
234 const size_t upper_idx
= i
< WORDCOUNT
? i
: WORDCOUNT
- 1;
235 for (size_t j
= lower_idx
; j
<= upper_idx
; ++j
) {
236 NumberPair
<uint64_t> prod
= full_mul(val
[j
], other
.val
[i
- j
]);
237 UInt
<128> tmp({prod
.lo
, prod
.hi
});
238 carry
+= partial_sum
.add(tmp
);
240 result
.val
[i
] = partial_sum
.val
[0];
241 partial_sum
.val
[0] = partial_sum
.val
[1];
242 partial_sum
.val
[1] = carry
;
245 result
.val
[WORDCOUNT
+ OTHER_WORDCOUNT
- 1] = partial_sum
.val
[0];
249 // Fast hi part of the full product. The normal product `operator*` returns
250 // `Bits` least significant bits of the full product, while this function will
251 // approximate `Bits` most significant bits of the full product with errors
253 // 0 <= (a.full_mul(b) >> Bits) - a.quick_mul_hi(b)) <= WORDCOUNT - 1.
255 // An example usage of this is to quickly (but less accurately) compute the
256 // product of (normalized) mantissas of floating point numbers:
257 // (mant_1, mant_2) -> quick_mul_hi -> normalize leading bit
258 // is much more efficient than:
259 // (mant_1, mant_2) -> ful_mul -> normalize leading bit
260 // -> convert back to same Bits width by shifting/rounding,
261 // especially for higher precisions.
263 // Performance summary:
264 // Number of 64-bit x 64-bit -> 128-bit multiplications performed.
265 // Bits WORDCOUNT ful_mul quick_mul_hi Error bound
270 constexpr UInt
<Bits
> quick_mul_hi(const UInt
<Bits
> &other
) const {
271 UInt
<Bits
> result(0);
272 UInt
<128> partial_sum(0);
274 // First round of accumulation for those at WORDCOUNT - 1 in the full
276 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
277 NumberPair
<uint64_t> prod
=
278 full_mul(val
[i
], other
.val
[WORDCOUNT
- 1 - i
]);
279 UInt
<128> tmp({prod
.lo
, prod
.hi
});
280 carry
+= partial_sum
.add(tmp
);
282 for (size_t i
= WORDCOUNT
; i
< 2 * WORDCOUNT
- 1; ++i
) {
283 partial_sum
.val
[0] = partial_sum
.val
[1];
284 partial_sum
.val
[1] = carry
;
286 for (size_t j
= i
- WORDCOUNT
+ 1; j
< WORDCOUNT
; ++j
) {
287 NumberPair
<uint64_t> prod
= full_mul(val
[j
], other
.val
[i
- j
]);
288 UInt
<128> tmp({prod
.lo
, prod
.hi
});
289 carry
+= partial_sum
.add(tmp
);
291 result
.val
[i
- WORDCOUNT
] = partial_sum
.val
[0];
293 result
.val
[WORDCOUNT
- 1] = partial_sum
.val
[1];
297 // pow takes a power and sets this to its starting value to that power. Zero
298 // to the zeroth power returns 1.
299 constexpr void pow_n(uint64_t power
) {
300 UInt
<Bits
> result
= 1;
301 UInt
<Bits
> cur_power
= *this;
304 if ((power
% 2) > 0) {
305 result
= result
* cur_power
;
308 cur_power
*= cur_power
;
313 // div takes another UInt of the same size and divides this by it. The value
314 // of this will be set to the quotient, and the return value is the remainder.
315 constexpr optional
<UInt
<Bits
>> div(const UInt
<Bits
> &other
) {
316 UInt
<Bits
> remainder(0);
319 *this = UInt
<Bits
>(0);
329 UInt
<Bits
> quotient(0);
330 UInt
<Bits
> subtractor
= other
;
331 int cur_bit
= subtractor
.clz() - this->clz();
332 subtractor
.shift_left(cur_bit
);
334 for (; cur_bit
>= 0 && *this > 0; --cur_bit
, subtractor
.shift_right(1)) {
335 if (*this >= subtractor
) {
336 this->sub(subtractor
);
337 quotient
= quotient
| (UInt
<Bits
>(1) << cur_bit
);
345 // Efficiently perform UInt / (x * 2^e), where x is a 32-bit unsigned integer,
346 // and return the remainder.
347 // The main idea is as follow:
348 // Let q = y / (x * 2^e) be the quotient, and
349 // r = y % (x * 2^e) be the remainder.
350 // First, notice that:
351 // r % (2^e) = y % (2^e),
352 // so we just need to focus on all the bits of y that is >= 2^e.
353 // To speed up the shift-and-add steps, we only use x as the divisor, and
354 // performing 32-bit shiftings instead of bit-by-bit shiftings.
355 // Since the remainder of each division step < x < 2^32, the computation of
356 // each step is now properly contained within uint64_t.
357 // And finally we perform some extra alignment steps for the remaining bits.
358 constexpr optional
<UInt
<Bits
>> div_uint32_times_pow_2(uint32_t x
, size_t e
) {
359 UInt
<Bits
> remainder(0);
366 *this = UInt
<Bits
>(0);
370 UInt
<Bits
> quotient(0);
371 uint64_t x64
= static_cast<uint64_t>(x
);
372 // lower64 = smallest multiple of 64 that is >= e.
373 size_t lower64
= ((e
>> 6) + ((e
& 63) != 0)) << 6;
374 // lower_pos is the index of the closest 64-bit chunk >= 2^e.
375 size_t lower_pos
= lower64
/ 64;
376 // Keep track of current remainder mod x * 2^(32*i)
378 // pos is the index of the current 64-bit chunk that we are processing.
379 size_t pos
= WORDCOUNT
;
381 for (size_t q_pos
= WORDCOUNT
- lower_pos
; q_pos
> 0; --q_pos
) {
382 // q_pos is 1 + the index of the current 64-bit chunk of the quotient
384 // Performing the division / modulus with divisor:
385 // x * 2^(64*q_pos - 32),
386 // i.e. using the upper 32-bit of the current 64-bit chunk.
388 rem
+= val
[--pos
] >> 32;
389 uint64_t q_tmp
= rem
/ x64
;
392 // Performing the division / modulus with divisor:
393 // x * 2^(64*(q_pos - 1)),
394 // i.e. using the lower 32-bit of the current 64-bit chunk.
396 rem
+= val
[pos
] & MASK32
;
397 quotient
.val
[q_pos
- 1] = (q_tmp
<< 32) + rem
/ x64
;
401 // So far, what we have is:
402 // quotient = y / (x * 2^lower64), and
403 // rem = (y % (x * 2^lower64)) / 2^lower64.
404 // If (lower64 > e), we will need to perform an extra adjustment of the
405 // quotient and remainder, namely:
406 // y / (x * 2^e) = [ y / (x * 2^lower64) ] * 2^(lower64 - e) +
407 // + (rem * 2^(lower64 - e)) / x
408 // (y % (x * 2^e)) / 2^e = (rem * 2^(lower64 - e)) % x
409 size_t last_shift
= lower64
- e
;
411 if (last_shift
> 0) {
412 // quotient * 2^(lower64 - e)
413 quotient
<<= last_shift
;
415 uint64_t d
= val
[--pos
];
416 if (last_shift
>= 32) {
417 // The shifting (rem * 2^(lower64 - e)) might overflow uint64_t, so we
418 // perform a 32-bit shift first.
426 // Only use the upper 32-bit of the current 64-bit chunk.
430 if (last_shift
> 0) {
433 q_tmp
<<= last_shift
;
434 x64
<<= 32 - last_shift
;
439 quotient
.val
[0] += q_tmp
;
441 if (lower64
- e
<= 32) {
442 // The remainder rem * 2^(lower64 - e) might overflow to the higher
444 if (pos
< WORDCOUNT
- 1) {
445 remainder
[pos
+ 1] = rem
>> 32;
447 remainder
[pos
] = (rem
<< 32) + (val
[pos
] & MASK32
);
449 remainder
[pos
] = rem
;
453 remainder
[pos
] = rem
;
456 // Set the remaining lower bits of the remainder.
457 for (; pos
> 0; --pos
) {
458 remainder
[pos
- 1] = val
[pos
- 1];
465 constexpr UInt
<Bits
> operator/(const UInt
<Bits
> &other
) const {
466 UInt
<Bits
> result(*this);
471 constexpr UInt
<Bits
> operator%(const UInt
<Bits
> &other
) const {
472 UInt
<Bits
> result(*this);
473 return *result
.div(other
);
476 constexpr UInt
<Bits
> &operator*=(const UInt
<Bits
> &other
) {
477 *this = *this * other
;
481 constexpr uint64_t clz() {
482 uint64_t leading_zeroes
= 0;
483 for (size_t i
= WORDCOUNT
; i
> 0; --i
) {
484 if (val
[i
- 1] == 0) {
485 leading_zeroes
+= sizeof(uint64_t) * 8;
487 leading_zeroes
+= unsafe_clz(val
[i
- 1]);
491 return leading_zeroes
;
494 constexpr void shift_left(size_t s
) {
495 #ifdef __SIZEOF_INT128__
496 if constexpr (Bits
== 128) {
497 // Use builtin 128 bits if available;
503 __uint128_t tmp
= __uint128_t(val
[0]) + (__uint128_t(val
[1]) << 64);
505 val
[0] = uint64_t(tmp
);
506 val
[1] = uint64_t(tmp
>> 64);
509 #endif // __SIZEOF_INT128__
510 if (LIBC_UNLIKELY(s
== 0))
513 const size_t drop
= s
/ 64; // Number of words to drop
514 const size_t shift
= s
% 64; // Bits to shift in the remaining words.
515 size_t i
= WORDCOUNT
;
517 if (drop
< WORDCOUNT
) {
520 for (size_t j
= WORDCOUNT
- 1 - drop
; j
> 0; --i
, --j
) {
521 val
[i
] = (val
[j
] << shift
) | (val
[j
- 1] >> (64 - shift
));
523 val
[i
] = val
[0] << shift
;
525 for (size_t j
= WORDCOUNT
- 1 - drop
; j
> 0; --i
, --j
) {
532 for (size_t j
= 0; j
< i
; ++j
) {
537 constexpr UInt
<Bits
> operator<<(size_t s
) const {
538 UInt
<Bits
> result(*this);
539 result
.shift_left(s
);
543 constexpr UInt
<Bits
> &operator<<=(size_t s
) {
548 constexpr void shift_right(size_t s
) {
549 #ifdef __SIZEOF_INT128__
550 if constexpr (Bits
== 128) {
551 // Use builtin 128 bits if available;
557 __uint128_t tmp
= __uint128_t(val
[0]) + (__uint128_t(val
[1]) << 64);
559 val
[0] = uint64_t(tmp
);
560 val
[1] = uint64_t(tmp
>> 64);
563 #endif // __SIZEOF_INT128__
565 if (LIBC_UNLIKELY(s
== 0))
567 const size_t drop
= s
/ 64; // Number of words to drop
568 const size_t shift
= s
% 64; // Bit shift in the remaining words.
572 if (drop
< WORDCOUNT
) {
574 for (size_t j
= drop
; j
< WORDCOUNT
- 1; ++i
, ++j
) {
575 val
[i
] = (val
[j
] >> shift
) | (val
[j
+ 1] << (64 - shift
));
577 val
[i
] = val
[WORDCOUNT
- 1] >> shift
;
580 for (size_t j
= drop
; j
< WORDCOUNT
; ++i
, ++j
) {
586 for (; i
< WORDCOUNT
; ++i
) {
591 constexpr UInt
<Bits
> operator>>(size_t s
) const {
592 UInt
<Bits
> result(*this);
593 result
.shift_right(s
);
597 constexpr UInt
<Bits
> &operator>>=(size_t s
) {
602 constexpr UInt
<Bits
> operator&(const UInt
<Bits
> &other
) const {
604 for (size_t i
= 0; i
< WORDCOUNT
; ++i
)
605 result
.val
[i
] = val
[i
] & other
.val
[i
];
609 constexpr UInt
<Bits
> &operator&=(const UInt
<Bits
> &other
) {
610 for (size_t i
= 0; i
< WORDCOUNT
; ++i
)
611 val
[i
] &= other
.val
[i
];
615 constexpr UInt
<Bits
> operator|(const UInt
<Bits
> &other
) const {
617 for (size_t i
= 0; i
< WORDCOUNT
; ++i
)
618 result
.val
[i
] = val
[i
] | other
.val
[i
];
622 constexpr UInt
<Bits
> &operator|=(const UInt
<Bits
> &other
) {
623 for (size_t i
= 0; i
< WORDCOUNT
; ++i
)
624 val
[i
] |= other
.val
[i
];
628 constexpr UInt
<Bits
> operator^(const UInt
<Bits
> &other
) const {
630 for (size_t i
= 0; i
< WORDCOUNT
; ++i
)
631 result
.val
[i
] = val
[i
] ^ other
.val
[i
];
635 constexpr UInt
<Bits
> &operator^=(const UInt
<Bits
> &other
) {
636 for (size_t i
= 0; i
< WORDCOUNT
; ++i
)
637 val
[i
] ^= other
.val
[i
];
641 constexpr UInt
<Bits
> operator~() const {
643 for (size_t i
= 0; i
< WORDCOUNT
; ++i
)
644 result
.val
[i
] = ~val
[i
];
648 constexpr bool operator==(const UInt
<Bits
> &other
) const {
649 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
650 if (val
[i
] != other
.val
[i
])
656 constexpr bool operator!=(const UInt
<Bits
> &other
) const {
657 for (size_t i
= 0; i
< WORDCOUNT
; ++i
) {
658 if (val
[i
] != other
.val
[i
])
664 constexpr bool operator>(const UInt
<Bits
> &other
) const {
665 for (size_t i
= WORDCOUNT
; i
> 0; --i
) {
666 uint64_t word
= val
[i
- 1];
667 uint64_t other_word
= other
.val
[i
- 1];
668 if (word
> other_word
)
670 else if (word
< other_word
)
677 constexpr bool operator>=(const UInt
<Bits
> &other
) const {
678 for (size_t i
= WORDCOUNT
; i
> 0; --i
) {
679 uint64_t word
= val
[i
- 1];
680 uint64_t other_word
= other
.val
[i
- 1];
681 if (word
> other_word
)
683 else if (word
< other_word
)
690 constexpr bool operator<(const UInt
<Bits
> &other
) const {
691 for (size_t i
= WORDCOUNT
; i
> 0; --i
) {
692 uint64_t word
= val
[i
- 1];
693 uint64_t other_word
= other
.val
[i
- 1];
694 if (word
> other_word
)
696 else if (word
< other_word
)
703 constexpr bool operator<=(const UInt
<Bits
> &other
) const {
704 for (size_t i
= WORDCOUNT
; i
> 0; --i
) {
705 uint64_t word
= val
[i
- 1];
706 uint64_t other_word
= other
.val
[i
- 1];
707 if (word
> other_word
)
709 else if (word
< other_word
)
716 constexpr UInt
<Bits
> &operator++() {
722 // Return the i-th 64-bit word of the number.
723 constexpr const uint64_t &operator[](size_t i
) const { return val
[i
]; }
725 // Return the i-th 64-bit word of the number.
726 constexpr uint64_t &operator[](size_t i
) { return val
[i
]; }
728 uint64_t *data() { return val
; }
730 const uint64_t *data() const { return val
; }
733 // Provides limits of UInt<128>.
734 template <> class numeric_limits
<UInt
<128>> {
736 static constexpr UInt
<128> max() { return ~UInt
<128>(0); }
737 static constexpr UInt
<128> min() { return 0; }
740 // Provides is_integral of UInt<128>, UInt<192>, UInt<256>.
741 template <size_t Bits
> struct is_integral
<UInt
<Bits
>> : public cpp::true_type
{
742 static_assert(Bits
> 0 && Bits
% 64 == 0,
743 "Number of bits in UInt should be a multiple of 64.");
746 // Provides is_unsigned of UInt<128>, UInt<192>, UInt<256>.
747 template <size_t Bits
> struct is_unsigned
<UInt
<Bits
>> : public cpp::true_type
{
748 static_assert(Bits
> 0 && Bits
% 64 == 0,
749 "Number of bits in UInt should be a multiple of 64.");
752 } // namespace __llvm_libc::cpp
754 #endif // LLVM_LIBC_SRC_SUPPORT_UINT_H