[NFC][Py Reformat] Added more commits to .git-blame-ignore-revs
[llvm-project.git] / libc / src / __support / UInt.h
bloba702aaad827b2584407651431b0973b89753cfc2
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 //===----------------------------------------------------------------------===//
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
22 #include <stdint.h>
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)
45 val[i] = other[i];
46 } else {
47 size_t i = 0;
48 for (; i < OtherBits / 64; ++i)
49 val[i] = other[i];
50 for (; i < WORDCOUNT; ++i)
51 val[i] = 0;
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;
59 size_t i = 0;
60 for (; i < min_wordcount; ++i)
61 val[i] = nums[i];
63 // If nums doesn't completely fill val, then fill the rest with zeroes.
64 for (; i < WORDCOUNT; ++i)
65 val[i] = 0;
68 // Initialize the first word to |v| and the rest to 0.
69 constexpr UInt(uint64_t v) {
70 val[0] = v;
71 for (size_t i = 1; i < WORDCOUNT; ++i) {
72 val[i] = 0;
75 constexpr explicit UInt(const cpp::array<uint64_t, WORDCOUNT> &words) {
76 for (size_t i = 0; i < WORDCOUNT; ++i)
77 val[i] = words[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) {
100 if (val[i] != 0)
101 return false;
103 return true;
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);
112 val[i] = s.sum;
114 return s.carry;
117 UInt<Bits> operator+(const UInt<Bits> &other) const {
118 UInt<Bits> result;
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;
124 return result;
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 {
130 UInt<Bits> result;
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;
136 return result;
139 constexpr UInt<Bits> &operator+=(const UInt<Bits> &other) {
140 add(other); // Returned carry value is ignored.
141 return *this;
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);
150 val[i] = d.diff;
152 return d.borrow;
155 UInt<Bits> operator-(const UInt<Bits> &other) const {
156 UInt<Bits> result;
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;
162 return result;
165 constexpr UInt<Bits> operator-(UInt<Bits> &&other) const {
166 UInt<Bits> result;
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;
172 return result;
175 constexpr UInt<Bits> &operator-=(const UInt<Bits> &other) {
176 // TODO(lntue): Set overflow flag / errno when carry is true.
177 sub(other);
178 return *this;
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
185 // carry bits.
186 // Returns the carry value produced by the multiplication operation.
187 constexpr uint64_t mul(uint64_t x) {
188 UInt<128> partial_sum(0);
189 uint64_t carry = 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;
197 carry = 0;
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]};
205 } else {
206 UInt<Bits> result(0);
207 UInt<128> partial_sum(0);
208 uint64_t carry = 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;
218 carry = 0;
220 return result;
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);
229 uint64_t carry = 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;
243 carry = 0;
245 result.val[WORDCOUNT + OTHER_WORDCOUNT - 1] = partial_sum.val[0];
246 return result;
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
252 // bounded by:
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
266 // 128 2 4 3 1
267 // 196 3 9 6 2
268 // 256 4 16 10 3
269 // 512 8 64 36 7
270 constexpr UInt<Bits> quick_mul_hi(const UInt<Bits> &other) const {
271 UInt<Bits> result(0);
272 UInt<128> partial_sum(0);
273 uint64_t carry = 0;
274 // First round of accumulation for those at WORDCOUNT - 1 in the full
275 // product.
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;
285 carry = 0;
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];
294 return result;
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;
303 while (power > 0) {
304 if ((power % 2) > 0) {
305 result = result * cur_power;
307 power = power >> 1;
308 cur_power *= cur_power;
310 *this = result;
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);
317 if (*this < other) {
318 remainder = *this;
319 *this = UInt<Bits>(0);
320 return remainder;
322 if (other == 1) {
323 return remainder;
325 if (other == 0) {
326 return nullopt;
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);
340 remainder = *this;
341 *this = quotient;
342 return remainder;
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);
361 if (x == 0) {
362 return nullopt;
364 if (e >= Bits) {
365 remainder = *this;
366 *this = UInt<Bits>(0);
367 return remainder;
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)
377 uint64_t rem = 0;
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
383 // being processed.
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.
387 rem <<= 32;
388 rem += val[--pos] >> 32;
389 uint64_t q_tmp = rem / x64;
390 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.
395 rem <<= 32;
396 rem += val[pos] & MASK32;
397 quotient.val[q_pos - 1] = (q_tmp << 32) + rem / x64;
398 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;
414 uint64_t q_tmp = 0;
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.
419 rem <<= 32;
420 rem += d >> 32;
421 d &= MASK32;
422 q_tmp = rem / x64;
423 rem %= x64;
424 last_shift -= 32;
425 } else {
426 // Only use the upper 32-bit of the current 64-bit chunk.
427 d >>= 32;
430 if (last_shift > 0) {
431 rem <<= 32;
432 rem += d;
433 q_tmp <<= last_shift;
434 x64 <<= 32 - last_shift;
435 q_tmp += rem / x64;
436 rem %= x64;
439 quotient.val[0] += q_tmp;
441 if (lower64 - e <= 32) {
442 // The remainder rem * 2^(lower64 - e) might overflow to the higher
443 // 64-bit chunk.
444 if (pos < WORDCOUNT - 1) {
445 remainder[pos + 1] = rem >> 32;
447 remainder[pos] = (rem << 32) + (val[pos] & MASK32);
448 } else {
449 remainder[pos] = rem;
452 } else {
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];
461 *this = quotient;
462 return remainder;
465 constexpr UInt<Bits> operator/(const UInt<Bits> &other) const {
466 UInt<Bits> result(*this);
467 result.div(other);
468 return result;
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;
478 return *this;
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;
486 } else {
487 leading_zeroes += unsafe_clz(val[i - 1]);
488 break;
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;
498 if (s >= 128) {
499 val[0] = 0;
500 val[1] = 0;
501 return;
503 __uint128_t tmp = __uint128_t(val[0]) + (__uint128_t(val[1]) << 64);
504 tmp <<= s;
505 val[0] = uint64_t(tmp);
506 val[1] = uint64_t(tmp >> 64);
507 return;
509 #endif // __SIZEOF_INT128__
510 if (LIBC_UNLIKELY(s == 0))
511 return;
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) {
518 i = WORDCOUNT - 1;
519 if (shift > 0) {
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;
524 } else {
525 for (size_t j = WORDCOUNT - 1 - drop; j > 0; --i, --j) {
526 val[i] = val[j];
528 val[i] = val[0];
532 for (size_t j = 0; j < i; ++j) {
533 val[j] = 0;
537 constexpr UInt<Bits> operator<<(size_t s) const {
538 UInt<Bits> result(*this);
539 result.shift_left(s);
540 return result;
543 constexpr UInt<Bits> &operator<<=(size_t s) {
544 shift_left(s);
545 return *this;
548 constexpr void shift_right(size_t s) {
549 #ifdef __SIZEOF_INT128__
550 if constexpr (Bits == 128) {
551 // Use builtin 128 bits if available;
552 if (s >= 128) {
553 val[0] = 0;
554 val[1] = 0;
555 return;
557 __uint128_t tmp = __uint128_t(val[0]) + (__uint128_t(val[1]) << 64);
558 tmp >>= s;
559 val[0] = uint64_t(tmp);
560 val[1] = uint64_t(tmp >> 64);
561 return;
563 #endif // __SIZEOF_INT128__
565 if (LIBC_UNLIKELY(s == 0))
566 return;
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.
570 size_t i = 0;
572 if (drop < WORDCOUNT) {
573 if (shift > 0) {
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;
578 ++i;
579 } else {
580 for (size_t j = drop; j < WORDCOUNT; ++i, ++j) {
581 val[i] = val[j];
586 for (; i < WORDCOUNT; ++i) {
587 val[i] = 0;
591 constexpr UInt<Bits> operator>>(size_t s) const {
592 UInt<Bits> result(*this);
593 result.shift_right(s);
594 return result;
597 constexpr UInt<Bits> &operator>>=(size_t s) {
598 shift_right(s);
599 return *this;
602 constexpr UInt<Bits> operator&(const UInt<Bits> &other) const {
603 UInt<Bits> result;
604 for (size_t i = 0; i < WORDCOUNT; ++i)
605 result.val[i] = val[i] & other.val[i];
606 return result;
609 constexpr UInt<Bits> &operator&=(const UInt<Bits> &other) {
610 for (size_t i = 0; i < WORDCOUNT; ++i)
611 val[i] &= other.val[i];
612 return *this;
615 constexpr UInt<Bits> operator|(const UInt<Bits> &other) const {
616 UInt<Bits> result;
617 for (size_t i = 0; i < WORDCOUNT; ++i)
618 result.val[i] = val[i] | other.val[i];
619 return result;
622 constexpr UInt<Bits> &operator|=(const UInt<Bits> &other) {
623 for (size_t i = 0; i < WORDCOUNT; ++i)
624 val[i] |= other.val[i];
625 return *this;
628 constexpr UInt<Bits> operator^(const UInt<Bits> &other) const {
629 UInt<Bits> result;
630 for (size_t i = 0; i < WORDCOUNT; ++i)
631 result.val[i] = val[i] ^ other.val[i];
632 return result;
635 constexpr UInt<Bits> &operator^=(const UInt<Bits> &other) {
636 for (size_t i = 0; i < WORDCOUNT; ++i)
637 val[i] ^= other.val[i];
638 return *this;
641 constexpr UInt<Bits> operator~() const {
642 UInt<Bits> result;
643 for (size_t i = 0; i < WORDCOUNT; ++i)
644 result.val[i] = ~val[i];
645 return result;
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])
651 return false;
653 return true;
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])
659 return true;
661 return false;
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)
669 return true;
670 else if (word < other_word)
671 return false;
673 // Equal
674 return false;
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)
682 return true;
683 else if (word < other_word)
684 return false;
686 // Equal
687 return true;
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)
695 return false;
696 else if (word < other_word)
697 return true;
699 // Equal
700 return false;
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)
708 return false;
709 else if (word < other_word)
710 return true;
712 // Equal
713 return true;
716 constexpr UInt<Bits> &operator++() {
717 UInt<Bits> one(1);
718 add(one);
719 return *this;
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>> {
735 public:
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