Path: blob/main/contrib/llvm-project/libc/src/__support/big_int.h
213766 views
//===-- A class to manipulate wide integers. --------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIBC_SRC___SUPPORT_BIG_INT_H9#define LLVM_LIBC_SRC___SUPPORT_BIG_INT_H1011#include "src/__support/CPP/array.h"12#include "src/__support/CPP/bit.h" // countl_zero13#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/macros/attributes.h" // LIBC_INLINE17#include "src/__support/macros/config.h"18#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY19#include "src/__support/macros/properties/compiler.h" // LIBC_COMPILER_IS_CLANG20#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128, LIBC_TYPES_HAS_INT6421#include "src/__support/math_extras.h" // add_with_carry, sub_with_borrow22#include "src/__support/number_pair.h"2324#include <stddef.h> // For size_t25#include <stdint.h>2627namespace LIBC_NAMESPACE_DECL {2829namespace multiword {3031// A type trait mapping unsigned integers to their half-width unsigned32// counterparts.33template <typename T> struct half_width;34template <> struct half_width<uint16_t> : cpp::type_identity<uint8_t> {};35template <> struct half_width<uint32_t> : cpp::type_identity<uint16_t> {};36#ifdef LIBC_TYPES_HAS_INT6437template <> struct half_width<uint64_t> : cpp::type_identity<uint32_t> {};38#ifdef LIBC_TYPES_HAS_INT12839template <> struct half_width<__uint128_t> : cpp::type_identity<uint64_t> {};40#endif // LIBC_TYPES_HAS_INT12841#endif // LIBC_TYPES_HAS_INT6442template <typename T> using half_width_t = typename half_width<T>::type;4344// An array of two elements that can be used in multiword operations.45template <typename T> struct DoubleWide final : cpp::array<T, 2> {46using UP = cpp::array<T, 2>;47using UP::UP;48LIBC_INLINE constexpr DoubleWide(T lo, T hi) : UP({lo, hi}) {}49};5051// Converts an unsigned value into a DoubleWide<half_width_t<T>>.52template <typename T> LIBC_INLINE constexpr auto split(T value) {53static_assert(cpp::is_unsigned_v<T>);54using half_type = half_width_t<T>;55return DoubleWide<half_type>(56half_type(value),57half_type(value >> cpp::numeric_limits<half_type>::digits));58}5960// The low part of a DoubleWide value.61template <typename T> LIBC_INLINE constexpr T lo(const DoubleWide<T> &value) {62return value[0];63}64// The high part of a DoubleWide value.65template <typename T> LIBC_INLINE constexpr T hi(const DoubleWide<T> &value) {66return value[1];67}68// The low part of an unsigned value.69template <typename T> LIBC_INLINE constexpr half_width_t<T> lo(T value) {70return lo(split(value));71}72// The high part of an unsigned value.73template <typename T> LIBC_INLINE constexpr half_width_t<T> hi(T value) {74return hi(split(value));75}7677// Returns 'a' times 'b' in a DoubleWide<word>. Cannot overflow by construction.78template <typename word>79LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) {80if constexpr (cpp::is_same_v<word, uint8_t>) {81return split<uint16_t>(uint16_t(a) * uint16_t(b));82} else if constexpr (cpp::is_same_v<word, uint16_t>) {83return split<uint32_t>(uint32_t(a) * uint32_t(b));84}85#ifdef LIBC_TYPES_HAS_INT6486else if constexpr (cpp::is_same_v<word, uint32_t>) {87return split<uint64_t>(uint64_t(a) * uint64_t(b));88}89#endif90#ifdef LIBC_TYPES_HAS_INT12891else if constexpr (cpp::is_same_v<word, uint64_t>) {92return split<__uint128_t>(__uint128_t(a) * __uint128_t(b));93}94#endif95else {96using half_word = half_width_t<word>;97const auto shiftl = [](word value) -> word {98return value << cpp::numeric_limits<half_word>::digits;99};100const auto shiftr = [](word value) -> word {101return value >> cpp::numeric_limits<half_word>::digits;102};103// Here we do a one digit multiplication where 'a' and 'b' are of type104// word. We split 'a' and 'b' into half words and perform the classic long105// multiplication with 'a' and 'b' being two-digit numbers.106107// a a_hi a_lo108// x b => x b_hi b_lo109// ---- -----------110// c result111// We convert 'lo' and 'hi' from 'half_word' to 'word' so multiplication112// doesn't overflow.113const word a_lo = lo(a);114const word b_lo = lo(b);115const word a_hi = hi(a);116const word b_hi = hi(b);117const word step1 = b_lo * a_lo; // no overflow;118const word step2 = b_lo * a_hi; // no overflow;119const word step3 = b_hi * a_lo; // no overflow;120const word step4 = b_hi * a_hi; // no overflow;121word lo_digit = step1;122word hi_digit = step4;123const word no_carry = 0;124word carry;125word _; // unused carry variable.126lo_digit = add_with_carry<word>(lo_digit, shiftl(step2), no_carry, carry);127hi_digit = add_with_carry<word>(hi_digit, shiftr(step2), carry, _);128lo_digit = add_with_carry<word>(lo_digit, shiftl(step3), no_carry, carry);129hi_digit = add_with_carry<word>(hi_digit, shiftr(step3), carry, _);130return DoubleWide<word>(lo_digit, hi_digit);131}132}133134// In-place 'dst op= rhs' with operation with carry propagation. Returns carry.135template <typename Function, typename word, size_t N, size_t M>136LIBC_INLINE constexpr word inplace_binop(Function op_with_carry,137cpp::array<word, N> &dst,138const cpp::array<word, M> &rhs) {139static_assert(N >= M);140word carry_out = 0;141for (size_t i = 0; i < N; ++i) {142const bool has_rhs_value = i < M;143const word rhs_value = has_rhs_value ? rhs[i] : 0;144const word carry_in = carry_out;145dst[i] = op_with_carry(dst[i], rhs_value, carry_in, carry_out);146// stop early when rhs is over and no carry is to be propagated.147if (!has_rhs_value && carry_out == 0)148break;149}150return carry_out;151}152153// In-place addition. Returns carry.154template <typename word, size_t N, size_t M>155LIBC_INLINE constexpr word add_with_carry(cpp::array<word, N> &dst,156const cpp::array<word, M> &rhs) {157return inplace_binop(LIBC_NAMESPACE::add_with_carry<word>, dst, rhs);158}159160// In-place subtraction. Returns borrow.161template <typename word, size_t N, size_t M>162LIBC_INLINE constexpr word sub_with_borrow(cpp::array<word, N> &dst,163const cpp::array<word, M> &rhs) {164return inplace_binop(LIBC_NAMESPACE::sub_with_borrow<word>, dst, rhs);165}166167// In-place multiply-add. Returns carry.168// i.e., 'dst += b * c'169template <typename word, size_t N>170LIBC_INLINE constexpr word mul_add_with_carry(cpp::array<word, N> &dst, word b,171word c) {172return add_with_carry(dst, mul2(b, c));173}174175// An array of two elements serving as an accumulator during multiword176// computations.177template <typename T> struct Accumulator final : cpp::array<T, 2> {178using UP = cpp::array<T, 2>;179LIBC_INLINE constexpr Accumulator() : UP({0, 0}) {}180LIBC_INLINE constexpr T advance(T carry_in) {181auto result = UP::front();182UP::front() = UP::back();183UP::back() = carry_in;184return result;185}186LIBC_INLINE constexpr T sum() const { return UP::front(); }187LIBC_INLINE constexpr T carry() const { return UP::back(); }188};189190// In-place multiplication by a single word. Returns carry.191template <typename word, size_t N>192LIBC_INLINE constexpr word scalar_multiply_with_carry(cpp::array<word, N> &dst,193word x) {194Accumulator<word> acc;195for (auto &val : dst) {196const word carry = mul_add_with_carry(acc, val, x);197val = acc.advance(carry);198}199return acc.carry();200}201202// Multiplication of 'lhs' by 'rhs' into 'dst'. Returns carry.203// This function is safe to use for signed numbers.204// https://stackoverflow.com/a/20793834205// https://pages.cs.wisc.edu/%7Emarkhill/cs354/Fall2008/beyond354/int.mult.html206template <typename word, size_t O, size_t M, size_t N>207LIBC_INLINE constexpr word multiply_with_carry(cpp::array<word, O> &dst,208const cpp::array<word, M> &lhs,209const cpp::array<word, N> &rhs) {210static_assert(O >= M + N);211Accumulator<word> acc;212for (size_t i = 0; i < O; ++i) {213const size_t lower_idx = i < N ? 0 : i - N + 1;214const size_t upper_idx = i < M ? i : M - 1;215word carry = 0;216for (size_t j = lower_idx; j <= upper_idx; ++j)217carry += mul_add_with_carry(acc, lhs[j], rhs[i - j]);218dst[i] = acc.advance(carry);219}220return acc.carry();221}222223template <typename word, size_t N>224LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst,225const cpp::array<word, N> &lhs,226const cpp::array<word, N> &rhs) {227Accumulator<word> acc;228word carry = 0;229// First round of accumulation for those at N - 1 in the full product.230for (size_t i = 0; i < N; ++i)231carry += mul_add_with_carry(acc, lhs[i], rhs[N - 1 - i]);232for (size_t i = N; i < 2 * N - 1; ++i) {233acc.advance(carry);234carry = 0;235for (size_t j = i - N + 1; j < N; ++j)236carry += mul_add_with_carry(acc, lhs[j], rhs[i - j]);237dst[i - N] = acc.sum();238}239dst.back() = acc.carry();240}241242template <typename word, size_t N>243LIBC_INLINE constexpr bool is_negative(const cpp::array<word, N> &array) {244using signed_word = cpp::make_signed_t<word>;245return cpp::bit_cast<signed_word>(array.back()) < 0;246}247248// An enum for the shift function below.249enum Direction { LEFT, RIGHT };250251// A bitwise shift on an array of elements.252// 'offset' must be less than TOTAL_BITS (i.e., sizeof(word) * CHAR_BIT * N)253// otherwise the behavior is undefined.254template <Direction direction, bool is_signed, typename word, size_t N>255LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,256size_t offset) {257static_assert(direction == LEFT || direction == RIGHT);258constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits;259#ifdef LIBC_TYPES_HAS_INT128260constexpr size_t TOTAL_BITS = N * WORD_BITS;261if constexpr (TOTAL_BITS == 128) {262using type = cpp::conditional_t<is_signed, __int128_t, __uint128_t>;263auto tmp = cpp::bit_cast<type>(array);264if constexpr (direction == LEFT)265tmp <<= offset;266else267tmp >>= offset;268return cpp::bit_cast<cpp::array<word, N>>(tmp);269}270#endif271if (LIBC_UNLIKELY(offset == 0))272return array;273const bool is_neg = is_signed && is_negative(array);274constexpr auto at = [](size_t index) -> int {275// reverse iteration when direction == LEFT.276if constexpr (direction == LEFT)277return int(N) - int(index) - 1;278return int(index);279};280const auto safe_get_at = [&](size_t index) -> word {281// return appropriate value when accessing out of bound elements.282const int i = at(index);283if (i < 0)284return 0;285if (i >= int(N))286return is_neg ? cpp::numeric_limits<word>::max() : 0;287return array[static_cast<unsigned>(i)];288};289const size_t index_offset = offset / WORD_BITS;290const size_t bit_offset = offset % WORD_BITS;291#ifdef LIBC_COMPILER_IS_CLANG292__builtin_assume(index_offset < N);293#endif294cpp::array<word, N> out = {};295for (size_t index = 0; index < N; ++index) {296const word part1 = safe_get_at(index + index_offset);297const word part2 = safe_get_at(index + index_offset + 1);298word &dst = out[static_cast<unsigned>(at(index))];299if (bit_offset == 0)300dst = part1; // no crosstalk between parts.301else if constexpr (direction == LEFT)302dst = static_cast<word>((part1 << bit_offset) |303(part2 >> (WORD_BITS - bit_offset)));304else305dst = static_cast<word>((part1 >> bit_offset) |306(part2 << (WORD_BITS - bit_offset)));307}308return out;309}310311#define DECLARE_COUNTBIT(NAME, INDEX_EXPR) \312template <typename word, size_t N> \313LIBC_INLINE constexpr int NAME(const cpp::array<word, N> &val) { \314int bit_count = 0; \315for (size_t i = 0; i < N; ++i) { \316const int word_count = cpp::NAME<word>(val[INDEX_EXPR]); \317bit_count += word_count; \318if (word_count != cpp::numeric_limits<word>::digits) \319break; \320} \321return bit_count; \322}323324DECLARE_COUNTBIT(countr_zero, i) // iterating forward325DECLARE_COUNTBIT(countr_one, i) // iterating forward326DECLARE_COUNTBIT(countl_zero, N - i - 1) // iterating backward327DECLARE_COUNTBIT(countl_one, N - i - 1) // iterating backward328329} // namespace multiword330331template <size_t Bits, bool Signed, typename WordType = uint64_t>332struct BigInt {333private:334static_assert(cpp::is_integral_v<WordType> && cpp::is_unsigned_v<WordType>,335"WordType must be unsigned integer.");336337struct Division {338BigInt quotient;339BigInt remainder;340};341342public:343using word_type = WordType;344using unsigned_type = BigInt<Bits, false, word_type>;345using signed_type = BigInt<Bits, true, word_type>;346347LIBC_INLINE_VAR static constexpr bool SIGNED = Signed;348LIBC_INLINE_VAR static constexpr size_t BITS = Bits;349LIBC_INLINE_VAR350static constexpr size_t WORD_SIZE = sizeof(WordType) * CHAR_BIT;351352static_assert(Bits > 0 && Bits % WORD_SIZE == 0,353"Number of bits in BigInt should be a multiple of WORD_SIZE.");354355LIBC_INLINE_VAR static constexpr size_t WORD_COUNT = Bits / WORD_SIZE;356357cpp::array<WordType, WORD_COUNT> val{}; // zero initialized.358359LIBC_INLINE constexpr BigInt() = default;360361LIBC_INLINE constexpr BigInt(const BigInt &other) = default;362363template <size_t OtherBits, bool OtherSigned, typename OtherWordType>364LIBC_INLINE constexpr BigInt(365const BigInt<OtherBits, OtherSigned, OtherWordType> &other) {366using BigIntOther = BigInt<OtherBits, OtherSigned, OtherWordType>;367const bool should_sign_extend = Signed && other.is_neg();368369static_assert(!(Bits == OtherBits && WORD_SIZE != BigIntOther::WORD_SIZE) &&370"This is currently untested for casting between bigints with "371"the same bit width but different word sizes.");372373if constexpr (BigIntOther::WORD_SIZE < WORD_SIZE) {374// OtherWordType is smaller375constexpr size_t WORD_SIZE_RATIO = WORD_SIZE / BigIntOther::WORD_SIZE;376static_assert(377(WORD_SIZE % BigIntOther::WORD_SIZE) == 0 &&378"Word types must be multiples of each other for correct conversion.");379if constexpr (OtherBits >= Bits) { // truncate380// for each big word381for (size_t i = 0; i < WORD_COUNT; ++i) {382WordType cur_word = 0;383// combine WORD_SIZE_RATIO small words into a big word384for (size_t j = 0; j < WORD_SIZE_RATIO; ++j)385cur_word |= static_cast<WordType>(other[(i * WORD_SIZE_RATIO) + j])386<< (BigIntOther::WORD_SIZE * j);387388val[i] = cur_word;389}390} else { // zero or sign extend391size_t i = 0;392WordType cur_word = 0;393// for each small word394for (; i < BigIntOther::WORD_COUNT; ++i) {395// combine WORD_SIZE_RATIO small words into a big word396cur_word |= static_cast<WordType>(other[i])397<< (BigIntOther::WORD_SIZE * (i % WORD_SIZE_RATIO));398// if we've completed a big word, copy it into place and reset399if ((i % WORD_SIZE_RATIO) == WORD_SIZE_RATIO - 1) {400val[i / WORD_SIZE_RATIO] = cur_word;401cur_word = 0;402}403}404// Pretend there are extra words of the correct sign extension as needed405406const WordType extension_bits =407should_sign_extend ? cpp::numeric_limits<WordType>::max()408: cpp::numeric_limits<WordType>::min();409if ((i % WORD_SIZE_RATIO) != 0) {410cur_word |= static_cast<WordType>(extension_bits)411<< (BigIntOther::WORD_SIZE * (i % WORD_SIZE_RATIO));412}413// Copy the last word into place.414val[(i / WORD_SIZE_RATIO)] = cur_word;415extend((i / WORD_SIZE_RATIO) + 1, should_sign_extend);416}417} else if constexpr (BigIntOther::WORD_SIZE == WORD_SIZE) {418if constexpr (OtherBits >= Bits) { // truncate419for (size_t i = 0; i < WORD_COUNT; ++i)420val[i] = other[i];421} else { // zero or sign extend422size_t i = 0;423for (; i < BigIntOther::WORD_COUNT; ++i)424val[i] = other[i];425extend(i, should_sign_extend);426}427} else {428// OtherWordType is bigger.429constexpr size_t WORD_SIZE_RATIO = BigIntOther::WORD_SIZE / WORD_SIZE;430static_assert(431(BigIntOther::WORD_SIZE % WORD_SIZE) == 0 &&432"Word types must be multiples of each other for correct conversion.");433if constexpr (OtherBits >= Bits) { // truncate434// for each small word435for (size_t i = 0; i < WORD_COUNT; ++i) {436// split each big word into WORD_SIZE_RATIO small words437val[i] = static_cast<WordType>(other[i / WORD_SIZE_RATIO] >>438((i % WORD_SIZE_RATIO) * WORD_SIZE));439}440} else { // zero or sign extend441size_t i = 0;442// for each big word443for (; i < BigIntOther::WORD_COUNT; ++i) {444// split each big word into WORD_SIZE_RATIO small words445for (size_t j = 0; j < WORD_SIZE_RATIO; ++j)446val[(i * WORD_SIZE_RATIO) + j] =447static_cast<WordType>(other[i] >> (j * WORD_SIZE));448}449extend(i * WORD_SIZE_RATIO, should_sign_extend);450}451}452}453454// Construct a BigInt from a C array.455template <size_t N> LIBC_INLINE constexpr BigInt(const WordType (&nums)[N]) {456static_assert(N == WORD_COUNT);457for (size_t i = 0; i < WORD_COUNT; ++i)458val[i] = nums[i];459}460461LIBC_INLINE constexpr explicit BigInt(462const cpp::array<WordType, WORD_COUNT> &words) {463val = words;464}465466// Initialize the first word to |v| and the rest to 0.467template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T>>>468LIBC_INLINE constexpr BigInt(T v) {469constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;470const bool is_neg = v < 0;471for (size_t i = 0; i < WORD_COUNT; ++i) {472if (v == 0) {473extend(i, is_neg);474return;475}476val[i] = static_cast<WordType>(v);477if constexpr (T_SIZE > WORD_SIZE)478v >>= WORD_SIZE;479else480v = 0;481}482}483LIBC_INLINE constexpr BigInt &operator=(const BigInt &other) = default;484485// constants486LIBC_INLINE static constexpr BigInt zero() { return BigInt(); }487LIBC_INLINE static constexpr BigInt one() { return BigInt(1); }488LIBC_INLINE static constexpr BigInt all_ones() { return ~zero(); }489LIBC_INLINE static constexpr BigInt min() {490BigInt out;491if constexpr (SIGNED)492out.set_msb();493return out;494}495LIBC_INLINE static constexpr BigInt max() {496BigInt out = all_ones();497if constexpr (SIGNED)498out.clear_msb();499return out;500}501502// TODO: Reuse the Sign type.503LIBC_INLINE constexpr bool is_neg() const { return SIGNED && get_msb(); }504505template <size_t OtherBits, bool OtherSigned, typename OtherWordType>506LIBC_INLINE constexpr explicit507operator BigInt<OtherBits, OtherSigned, OtherWordType>() const {508return BigInt<OtherBits, OtherSigned, OtherWordType>(this);509}510511template <typename T> LIBC_INLINE constexpr explicit operator T() const {512return to<T>();513}514515template <typename T>516LIBC_INLINE constexpr cpp::enable_if_t<517cpp::is_integral_v<T> && !cpp::is_same_v<T, bool>, T>518to() const {519constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;520T lo = static_cast<T>(val[0]);521if constexpr (T_SIZE <= WORD_SIZE)522return lo;523constexpr size_t MAX_COUNT =524T_SIZE > Bits ? WORD_COUNT : T_SIZE / WORD_SIZE;525for (size_t i = 1; i < MAX_COUNT; ++i)526lo += static_cast<T>(static_cast<T>(val[i]) << (WORD_SIZE * i));527if constexpr (Signed && (T_SIZE > Bits)) {528// Extend sign for negative numbers.529constexpr T MASK = (~T(0) << Bits);530if (is_neg())531lo |= MASK;532}533return lo;534}535536LIBC_INLINE constexpr explicit operator bool() const { return !is_zero(); }537538LIBC_INLINE constexpr bool is_zero() const {539for (auto part : val)540if (part != 0)541return false;542return true;543}544545// Add 'rhs' to this number and store the result in this number.546// Returns the carry value produced by the addition operation.547LIBC_INLINE constexpr WordType add_overflow(const BigInt &rhs) {548return multiword::add_with_carry(val, rhs.val);549}550551LIBC_INLINE constexpr BigInt operator+(const BigInt &other) const {552BigInt result = *this;553result.add_overflow(other);554return result;555}556557// This will only apply when initializing a variable from constant values, so558// it will always use the constexpr version of add_with_carry.559LIBC_INLINE constexpr BigInt operator+(BigInt &&other) const {560// We use addition commutativity to reuse 'other' and prevent allocation.561other.add_overflow(*this); // Returned carry value is ignored.562return other;563}564565LIBC_INLINE constexpr BigInt &operator+=(const BigInt &other) {566add_overflow(other); // Returned carry value is ignored.567return *this;568}569570// Subtract 'rhs' to this number and store the result in this number.571// Returns the carry value produced by the subtraction operation.572LIBC_INLINE constexpr WordType sub_overflow(const BigInt &rhs) {573return multiword::sub_with_borrow(val, rhs.val);574}575576LIBC_INLINE constexpr BigInt operator-(const BigInt &other) const {577BigInt result = *this;578result.sub_overflow(other); // Returned carry value is ignored.579return result;580}581582LIBC_INLINE constexpr BigInt operator-(BigInt &&other) const {583BigInt result = *this;584result.sub_overflow(other); // Returned carry value is ignored.585return result;586}587588LIBC_INLINE constexpr BigInt &operator-=(const BigInt &other) {589// TODO(lntue): Set overflow flag / errno when carry is true.590sub_overflow(other); // Returned carry value is ignored.591return *this;592}593594// Multiply this number with x and store the result in this number.595LIBC_INLINE constexpr WordType mul(WordType x) {596return multiword::scalar_multiply_with_carry(val, x);597}598599// Return the full product.600template <size_t OtherBits>601LIBC_INLINE constexpr auto602ful_mul(const BigInt<OtherBits, Signed, WordType> &other) const {603BigInt<Bits + OtherBits, Signed, WordType> result;604multiword::multiply_with_carry(result.val, val, other.val);605return result;606}607608LIBC_INLINE constexpr BigInt operator*(const BigInt &other) const {609// Perform full mul and truncate.610return BigInt(ful_mul(other));611}612613// Fast hi part of the full product. The normal product `operator*` returns614// `Bits` least significant bits of the full product, while this function will615// approximate `Bits` most significant bits of the full product with errors616// bounded by:617// 0 <= (a.full_mul(b) >> Bits) - a.quick_mul_hi(b)) <= WORD_COUNT - 1.618//619// An example usage of this is to quickly (but less accurately) compute the620// product of (normalized) mantissas of floating point numbers:621// (mant_1, mant_2) -> quick_mul_hi -> normalize leading bit622// is much more efficient than:623// (mant_1, mant_2) -> ful_mul -> normalize leading bit624// -> convert back to same Bits width by shifting/rounding,625// especially for higher precisions.626//627// Performance summary:628// Number of 64-bit x 64-bit -> 128-bit multiplications performed.629// Bits WORD_COUNT ful_mul quick_mul_hi Error bound630// 128 2 4 3 1631// 196 3 9 6 2632// 256 4 16 10 3633// 512 8 64 36 7634LIBC_INLINE constexpr BigInt quick_mul_hi(const BigInt &other) const {635BigInt result;636multiword::quick_mul_hi(result.val, val, other.val);637return result;638}639640// BigInt(x).pow_n(n) computes x ^ n.641// Note 0 ^ 0 == 1.642LIBC_INLINE constexpr void pow_n(uint64_t power) {643static_assert(!Signed);644BigInt result = one();645BigInt cur_power = *this;646while (power > 0) {647if ((power % 2) > 0)648result *= cur_power;649power >>= 1;650cur_power *= cur_power;651}652*this = result;653}654655// Performs inplace signed / unsigned division. Returns remainder if not656// dividing by zero.657// For signed numbers it behaves like C++ signed integer division.658// That is by truncating the fractionnal part659// https://stackoverflow.com/a/3602857660LIBC_INLINE constexpr cpp::optional<BigInt> div(const BigInt ÷r) {661if (LIBC_UNLIKELY(divider.is_zero()))662return cpp::nullopt;663if (LIBC_UNLIKELY(divider == BigInt::one()))664return BigInt::zero();665Division result;666if constexpr (SIGNED)667result = divide_signed(*this, divider);668else669result = divide_unsigned(*this, divider);670*this = result.quotient;671return result.remainder;672}673674// Efficiently perform BigInt / (x * 2^e), where x is a half-word-size675// unsigned integer, and return the remainder. The main idea is as follow:676// Let q = y / (x * 2^e) be the quotient, and677// r = y % (x * 2^e) be the remainder.678// First, notice that:679// r % (2^e) = y % (2^e),680// so we just need to focus on all the bits of y that is >= 2^e.681// To speed up the shift-and-add steps, we only use x as the divisor, and682// performing 32-bit shiftings instead of bit-by-bit shiftings.683// Since the remainder of each division step < x < 2^(WORD_SIZE / 2), the684// computation of each step is now properly contained within WordType.685// And finally we perform some extra alignment steps for the remaining bits.686LIBC_INLINE constexpr cpp::optional<BigInt>687div_uint_half_times_pow_2(multiword::half_width_t<WordType> x, size_t e) {688BigInt remainder;689if (x == 0)690return cpp::nullopt;691if (e >= Bits) {692remainder = *this;693*this = BigInt<Bits, false, WordType>();694return remainder;695}696BigInt quotient;697WordType x_word = static_cast<WordType>(x);698constexpr size_t LOG2_WORD_SIZE =699static_cast<size_t>(cpp::bit_width(WORD_SIZE) - 1);700constexpr size_t HALF_WORD_SIZE = WORD_SIZE >> 1;701constexpr WordType HALF_MASK = ((WordType(1) << HALF_WORD_SIZE) - 1);702// lower = smallest multiple of WORD_SIZE that is >= e.703size_t lower = ((e >> LOG2_WORD_SIZE) + ((e & (WORD_SIZE - 1)) != 0))704<< LOG2_WORD_SIZE;705// lower_pos is the index of the closest WORD_SIZE-bit chunk >= 2^e.706size_t lower_pos = lower / WORD_SIZE;707// Keep track of current remainder mod x * 2^(32*i)708WordType rem = 0;709// pos is the index of the current 64-bit chunk that we are processing.710size_t pos = WORD_COUNT;711712// TODO: look into if constexpr(Bits > 256) skip leading zeroes.713714for (size_t q_pos = WORD_COUNT - lower_pos; q_pos > 0; --q_pos) {715// q_pos is 1 + the index of the current WORD_SIZE-bit chunk of the716// quotient being processed. Performing the division / modulus with717// divisor:718// x * 2^(WORD_SIZE*q_pos - WORD_SIZE/2),719// i.e. using the upper (WORD_SIZE/2)-bit of the current WORD_SIZE-bit720// chunk.721rem <<= HALF_WORD_SIZE;722rem += val[--pos] >> HALF_WORD_SIZE;723WordType q_tmp = rem / x_word;724rem %= x_word;725726// Performing the division / modulus with divisor:727// x * 2^(WORD_SIZE*(q_pos - 1)),728// i.e. using the lower (WORD_SIZE/2)-bit of the current WORD_SIZE-bit729// chunk.730rem <<= HALF_WORD_SIZE;731rem += val[pos] & HALF_MASK;732quotient.val[q_pos - 1] = (q_tmp << HALF_WORD_SIZE) + rem / x_word;733rem %= x_word;734}735736// So far, what we have is:737// quotient = y / (x * 2^lower), and738// rem = (y % (x * 2^lower)) / 2^lower.739// If (lower > e), we will need to perform an extra adjustment of the740// quotient and remainder, namely:741// y / (x * 2^e) = [ y / (x * 2^lower) ] * 2^(lower - e) +742// + (rem * 2^(lower - e)) / x743// (y % (x * 2^e)) / 2^e = (rem * 2^(lower - e)) % x744size_t last_shift = lower - e;745746if (last_shift > 0) {747// quotient * 2^(lower - e)748quotient <<= last_shift;749WordType q_tmp = 0;750WordType d = val[--pos];751if (last_shift >= HALF_WORD_SIZE) {752// The shifting (rem * 2^(lower - e)) might overflow WordTyoe, so we753// perform a HALF_WORD_SIZE-bit shift first.754rem <<= HALF_WORD_SIZE;755rem += d >> HALF_WORD_SIZE;756d &= HALF_MASK;757q_tmp = rem / x_word;758rem %= x_word;759last_shift -= HALF_WORD_SIZE;760} else {761// Only use the upper HALF_WORD_SIZE-bit of the current WORD_SIZE-bit762// chunk.763d >>= HALF_WORD_SIZE;764}765766if (last_shift > 0) {767rem <<= HALF_WORD_SIZE;768rem += d;769q_tmp <<= last_shift;770x_word <<= HALF_WORD_SIZE - last_shift;771q_tmp += rem / x_word;772rem %= x_word;773}774775quotient.val[0] += q_tmp;776777if (lower - e <= HALF_WORD_SIZE) {778// The remainder rem * 2^(lower - e) might overflow to the higher779// WORD_SIZE-bit chunk.780if (pos < WORD_COUNT - 1) {781remainder[pos + 1] = rem >> HALF_WORD_SIZE;782}783remainder[pos] = (rem << HALF_WORD_SIZE) + (val[pos] & HALF_MASK);784} else {785remainder[pos] = rem;786}787788} else {789remainder[pos] = rem;790}791792// Set the remaining lower bits of the remainder.793for (; pos > 0; --pos) {794remainder[pos - 1] = val[pos - 1];795}796797*this = quotient;798return remainder;799}800801LIBC_INLINE constexpr BigInt operator/(const BigInt &other) const {802BigInt result(*this);803result.div(other);804return result;805}806807LIBC_INLINE constexpr BigInt &operator/=(const BigInt &other) {808div(other);809return *this;810}811812LIBC_INLINE constexpr BigInt operator%(const BigInt &other) const {813BigInt result(*this);814return *result.div(other);815}816817LIBC_INLINE constexpr BigInt operator%=(const BigInt &other) {818*this = *this % other;819return *this;820}821822LIBC_INLINE constexpr BigInt &operator*=(const BigInt &other) {823*this = *this * other;824return *this;825}826827LIBC_INLINE constexpr BigInt &operator<<=(size_t s) {828val = multiword::shift<multiword::LEFT, SIGNED>(val, s);829return *this;830}831832LIBC_INLINE constexpr BigInt operator<<(size_t s) const {833return BigInt(multiword::shift<multiword::LEFT, SIGNED>(val, s));834}835836LIBC_INLINE constexpr BigInt &operator>>=(size_t s) {837val = multiword::shift<multiword::RIGHT, SIGNED>(val, s);838return *this;839}840841LIBC_INLINE constexpr BigInt operator>>(size_t s) const {842return BigInt(multiword::shift<multiword::RIGHT, SIGNED>(val, s));843}844845#define DEFINE_BINOP(OP) \846LIBC_INLINE friend constexpr BigInt operator OP(const BigInt &lhs, \847const BigInt &rhs) { \848BigInt result; \849for (size_t i = 0; i < WORD_COUNT; ++i) \850result[i] = lhs[i] OP rhs[i]; \851return result; \852} \853LIBC_INLINE friend constexpr BigInt operator OP##=(BigInt &lhs, \854const BigInt &rhs) { \855for (size_t i = 0; i < WORD_COUNT; ++i) \856lhs[i] OP## = rhs[i]; \857return lhs; \858}859860DEFINE_BINOP(&) // & and &=861DEFINE_BINOP(|) // | and |=862DEFINE_BINOP(^) // ^ and ^=863#undef DEFINE_BINOP864865LIBC_INLINE constexpr BigInt operator~() const {866BigInt result;867for (size_t i = 0; i < WORD_COUNT; ++i)868result[i] = static_cast<WordType>(~val[i]);869return result;870}871872LIBC_INLINE constexpr BigInt operator-() const {873BigInt result(*this);874result.negate();875return result;876}877878LIBC_INLINE friend constexpr bool operator==(const BigInt &lhs,879const BigInt &rhs) {880for (size_t i = 0; i < WORD_COUNT; ++i)881if (lhs.val[i] != rhs.val[i])882return false;883return true;884}885886LIBC_INLINE friend constexpr bool operator!=(const BigInt &lhs,887const BigInt &rhs) {888return !(lhs == rhs);889}890891LIBC_INLINE friend constexpr bool operator>(const BigInt &lhs,892const BigInt &rhs) {893return cmp(lhs, rhs) > 0;894}895LIBC_INLINE friend constexpr bool operator>=(const BigInt &lhs,896const BigInt &rhs) {897return cmp(lhs, rhs) >= 0;898}899LIBC_INLINE friend constexpr bool operator<(const BigInt &lhs,900const BigInt &rhs) {901return cmp(lhs, rhs) < 0;902}903LIBC_INLINE friend constexpr bool operator<=(const BigInt &lhs,904const BigInt &rhs) {905return cmp(lhs, rhs) <= 0;906}907908LIBC_INLINE constexpr BigInt &operator++() {909increment();910return *this;911}912913LIBC_INLINE constexpr BigInt operator++(int) {914BigInt oldval(*this);915increment();916return oldval;917}918919LIBC_INLINE constexpr BigInt &operator--() {920decrement();921return *this;922}923924LIBC_INLINE constexpr BigInt operator--(int) {925BigInt oldval(*this);926decrement();927return oldval;928}929930// Return the i-th word of the number.931LIBC_INLINE constexpr const WordType &operator[](size_t i) const {932return val[i];933}934935// Return the i-th word of the number.936LIBC_INLINE constexpr WordType &operator[](size_t i) { return val[i]; }937938// Return the i-th bit of the number.939LIBC_INLINE constexpr bool get_bit(size_t i) const {940const size_t word_index = i / WORD_SIZE;941return 1 & (val[word_index] >> (i % WORD_SIZE));942}943944// Set the i-th bit of the number.945LIBC_INLINE constexpr void set_bit(size_t i) {946const size_t word_index = i / WORD_SIZE;947val[word_index] |= WordType(1) << (i % WORD_SIZE);948}949950private:951LIBC_INLINE friend constexpr int cmp(const BigInt &lhs, const BigInt &rhs) {952constexpr auto compare = [](WordType a, WordType b) {953return a == b ? 0 : a > b ? 1 : -1;954};955if constexpr (Signed) {956const bool lhs_is_neg = lhs.is_neg();957const bool rhs_is_neg = rhs.is_neg();958if (lhs_is_neg != rhs_is_neg)959return rhs_is_neg ? 1 : -1;960}961for (size_t i = WORD_COUNT; i-- > 0;)962if (auto cmp = compare(lhs[i], rhs[i]); cmp != 0)963return cmp;964return 0;965}966967LIBC_INLINE constexpr void bitwise_not() {968for (auto &part : val)969part = static_cast<WordType>(~part);970}971972LIBC_INLINE constexpr void negate() {973bitwise_not();974increment();975}976977LIBC_INLINE constexpr void increment() {978multiword::add_with_carry(val, cpp::array<WordType, 1>{1});979}980981LIBC_INLINE constexpr void decrement() {982multiword::sub_with_borrow(val, cpp::array<WordType, 1>{1});983}984985LIBC_INLINE constexpr void extend(size_t index, bool is_neg) {986const WordType value = is_neg ? cpp::numeric_limits<WordType>::max()987: cpp::numeric_limits<WordType>::min();988for (size_t i = index; i < WORD_COUNT; ++i)989val[i] = value;990}991992LIBC_INLINE constexpr bool get_msb() const {993return val.back() >> (WORD_SIZE - 1);994}995996LIBC_INLINE constexpr void set_msb() {997val.back() |= mask_leading_ones<WordType, 1>();998}9991000LIBC_INLINE constexpr void clear_msb() {1001val.back() &= mask_trailing_ones<WordType, WORD_SIZE - 1>();1002}1003LIBC_INLINE constexpr static Division divide_unsigned(const BigInt ÷nd,1004const BigInt ÷r) {1005BigInt remainder = dividend;1006BigInt quotient;1007if (remainder >= divider) {1008BigInt subtractor = divider;1009int cur_bit = multiword::countl_zero(subtractor.val) -1010multiword::countl_zero(remainder.val);1011subtractor <<= static_cast<size_t>(cur_bit);1012for (; cur_bit >= 0 && remainder > 0; --cur_bit, subtractor >>= 1) {1013if (remainder < subtractor)1014continue;1015remainder -= subtractor;1016quotient.set_bit(static_cast<size_t>(cur_bit));1017}1018}1019return Division{quotient, remainder};1020}10211022LIBC_INLINE constexpr static Division divide_signed(const BigInt ÷nd,1023const BigInt ÷r) {1024// Special case because it is not possible to negate the min value of a1025// signed integer.1026if (dividend == min() && divider == min())1027return Division{one(), zero()};1028// 1. Convert the dividend and divisor to unsigned representation.1029unsigned_type udividend(dividend);1030unsigned_type udivider(divider);1031// 2. Negate the dividend if it's negative, and similarly for the divisor.1032const bool dividend_is_neg = dividend.is_neg();1033const bool divider_is_neg = divider.is_neg();1034if (dividend_is_neg)1035udividend.negate();1036if (divider_is_neg)1037udivider.negate();1038// 3. Use unsigned multiword division algorithm.1039const auto unsigned_result = divide_unsigned(udividend, udivider);1040// 4. Convert the quotient and remainder to signed representation.1041Division result;1042result.quotient = signed_type(unsigned_result.quotient);1043result.remainder = signed_type(unsigned_result.remainder);1044// 5. Negate the quotient if the dividend and divisor had opposite signs.1045if (dividend_is_neg != divider_is_neg)1046result.quotient.negate();1047// 6. Negate the remainder if the dividend was negative.1048if (dividend_is_neg)1049result.remainder.negate();1050return result;1051}10521053friend signed_type;1054friend unsigned_type;1055};10561057namespace internal {1058// We default BigInt's WordType to 'uint64_t' or 'uint32_t' depending on type1059// availability.1060template <size_t Bits>1061struct WordTypeSelector : cpp::type_identity<1062#ifdef LIBC_TYPES_HAS_INT641063uint64_t1064#else1065uint32_t1066#endif // LIBC_TYPES_HAS_INT641067> {1068};1069// Except if we request 16 or 32 bits explicitly.1070template <> struct WordTypeSelector<16> : cpp::type_identity<uint16_t> {};1071template <> struct WordTypeSelector<32> : cpp::type_identity<uint32_t> {};1072template <> struct WordTypeSelector<96> : cpp::type_identity<uint32_t> {};10731074template <size_t Bits>1075using WordTypeSelectorT = typename WordTypeSelector<Bits>::type;1076} // namespace internal10771078template <size_t Bits>1079using UInt = BigInt<Bits, false, internal::WordTypeSelectorT<Bits>>;10801081template <size_t Bits>1082using Int = BigInt<Bits, true, internal::WordTypeSelectorT<Bits>>;10831084// Provides limits of BigInt.1085template <size_t Bits, bool Signed, typename T>1086struct cpp::numeric_limits<BigInt<Bits, Signed, T>> {1087LIBC_INLINE static constexpr BigInt<Bits, Signed, T> max() {1088return BigInt<Bits, Signed, T>::max();1089}1090LIBC_INLINE static constexpr BigInt<Bits, Signed, T> min() {1091return BigInt<Bits, Signed, T>::min();1092}1093// Meant to match std::numeric_limits interface.1094// NOLINTNEXTLINE(readability-identifier-naming)1095LIBC_INLINE_VAR static constexpr int digits = Bits - Signed;1096};10971098// type traits to determine whether a T is a BigInt.1099template <typename T> struct is_big_int : cpp::false_type {};11001101template <size_t Bits, bool Signed, typename T>1102struct is_big_int<BigInt<Bits, Signed, T>> : cpp::true_type {};11031104template <class T>1105LIBC_INLINE_VAR constexpr bool is_big_int_v = is_big_int<T>::value;11061107// extensions of type traits to include BigInt11081109// is_integral_or_big_int1110template <typename T>1111struct is_integral_or_big_int1112: cpp::bool_constant<(cpp::is_integral_v<T> || is_big_int_v<T>)> {};11131114template <typename T>1115LIBC_INLINE_VAR constexpr bool is_integral_or_big_int_v =1116is_integral_or_big_int<T>::value;11171118// make_big_int_unsigned1119template <typename T> struct make_big_int_unsigned;11201121template <size_t Bits, bool Signed, typename T>1122struct make_big_int_unsigned<BigInt<Bits, Signed, T>>1123: cpp::type_identity<BigInt<Bits, false, T>> {};11241125template <typename T>1126using make_big_int_unsigned_t = typename make_big_int_unsigned<T>::type;11271128// make_big_int_signed1129template <typename T> struct make_big_int_signed;11301131template <size_t Bits, bool Signed, typename T>1132struct make_big_int_signed<BigInt<Bits, Signed, T>>1133: cpp::type_identity<BigInt<Bits, true, T>> {};11341135template <typename T>1136using make_big_int_signed_t = typename make_big_int_signed<T>::type;11371138// make_integral_or_big_int_unsigned1139template <typename T, class = void> struct make_integral_or_big_int_unsigned;11401141template <typename T>1142struct make_integral_or_big_int_unsigned<1143T, cpp::enable_if_t<cpp::is_integral_v<T>>> : cpp::make_unsigned<T> {};11441145template <typename T>1146struct make_integral_or_big_int_unsigned<T, cpp::enable_if_t<is_big_int_v<T>>>1147: make_big_int_unsigned<T> {};11481149template <typename T>1150using make_integral_or_big_int_unsigned_t =1151typename make_integral_or_big_int_unsigned<T>::type;11521153// make_integral_or_big_int_signed1154template <typename T, class = void> struct make_integral_or_big_int_signed;11551156template <typename T>1157struct make_integral_or_big_int_signed<T,1158cpp::enable_if_t<cpp::is_integral_v<T>>>1159: cpp::make_signed<T> {};11601161template <typename T>1162struct make_integral_or_big_int_signed<T, cpp::enable_if_t<is_big_int_v<T>>>1163: make_big_int_signed<T> {};11641165template <typename T>1166using make_integral_or_big_int_signed_t =1167typename make_integral_or_big_int_signed<T>::type;11681169// is_unsigned_integral_or_big_int1170template <typename T>1171struct is_unsigned_integral_or_big_int1172: cpp::bool_constant<1173cpp::is_same_v<T, make_integral_or_big_int_unsigned_t<T>>> {};11741175template <typename T>1176// Meant to look like <type_traits> helper variable templates.1177// NOLINTNEXTLINE(readability-identifier-naming)1178LIBC_INLINE_VAR constexpr bool is_unsigned_integral_or_big_int_v =1179is_unsigned_integral_or_big_int<T>::value;11801181namespace cpp {11821183// Specialization of cpp::bit_cast ('bit.h') from T to BigInt.1184template <typename To, typename From>1185LIBC_INLINE constexpr cpp::enable_if_t<1186(sizeof(To) == sizeof(From)) && cpp::is_trivially_copyable<To>::value &&1187cpp::is_trivially_copyable<From>::value && is_big_int<To>::value,1188To>1189bit_cast(const From &from) {1190To out;1191using Storage = decltype(out.val);1192out.val = cpp::bit_cast<Storage>(from);1193return out;1194}11951196// Specialization of cpp::bit_cast ('bit.h') from BigInt to T.1197template <typename To, size_t Bits>1198LIBC_INLINE constexpr cpp::enable_if_t<1199sizeof(To) == sizeof(UInt<Bits>) &&1200cpp::is_trivially_constructible<To>::value &&1201cpp::is_trivially_copyable<To>::value &&1202cpp::is_trivially_copyable<UInt<Bits>>::value,1203To>1204bit_cast(const UInt<Bits> &from) {1205return cpp::bit_cast<To>(from.val);1206}12071208// Specialization of cpp::popcount ('bit.h') for BigInt.1209template <typename T>1210[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1211popcount(T value) {1212int bits = 0;1213for (auto word : value.val)1214if (word)1215bits += popcount(word);1216return bits;1217}12181219// Specialization of cpp::has_single_bit ('bit.h') for BigInt.1220template <typename T>1221[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, bool>1222has_single_bit(T value) {1223int bits = 0;1224for (auto word : value.val) {1225if (word == 0)1226continue;1227bits += popcount(word);1228if (bits > 1)1229return false;1230}1231return bits == 1;1232}12331234// Specialization of cpp::countr_zero ('bit.h') for BigInt.1235template <typename T>1236[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1237countr_zero(const T &value) {1238return multiword::countr_zero(value.val);1239}12401241// Specialization of cpp::countl_zero ('bit.h') for BigInt.1242template <typename T>1243[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1244countl_zero(const T &value) {1245return multiword::countl_zero(value.val);1246}12471248// Specialization of cpp::countl_one ('bit.h') for BigInt.1249template <typename T>1250[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1251countl_one(T value) {1252return multiword::countl_one(value.val);1253}12541255// Specialization of cpp::countr_one ('bit.h') for BigInt.1256template <typename T>1257[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1258countr_one(T value) {1259return multiword::countr_one(value.val);1260}12611262// Specialization of cpp::bit_width ('bit.h') for BigInt.1263template <typename T>1264[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1265bit_width(T value) {1266return cpp::numeric_limits<T>::digits - cpp::countl_zero(value);1267}12681269// Forward-declare rotr so that rotl can use it.1270template <typename T>1271[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>1272rotr(T value, int rotate);12731274// Specialization of cpp::rotl ('bit.h') for BigInt.1275template <typename T>1276[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>1277rotl(T value, int rotate) {1278constexpr int N = cpp::numeric_limits<T>::digits;1279rotate = rotate % N;1280if (!rotate)1281return value;1282if (rotate < 0)1283return cpp::rotr<T>(value, -rotate);1284return (value << static_cast<size_t>(rotate)) |1285(value >> (N - static_cast<size_t>(rotate)));1286}12871288// Specialization of cpp::rotr ('bit.h') for BigInt.1289template <typename T>1290[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>1291rotr(T value, int rotate) {1292constexpr int N = cpp::numeric_limits<T>::digits;1293rotate = rotate % N;1294if (!rotate)1295return value;1296if (rotate < 0)1297return cpp::rotl<T>(value, -rotate);1298return (value >> static_cast<size_t>(rotate)) |1299(value << (N - static_cast<size_t>(rotate)));1300}13011302} // namespace cpp13031304// Specialization of mask_trailing_ones ('math_extras.h') for BigInt.1305template <typename T, size_t count>1306LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>1307mask_trailing_ones() {1308static_assert(!T::SIGNED && count <= T::BITS);1309if (count == T::BITS)1310return T::all_ones();1311constexpr size_t QUOTIENT = count / T::WORD_SIZE;1312constexpr size_t REMAINDER = count % T::WORD_SIZE;1313T out; // zero initialized1314for (size_t i = 0; i <= QUOTIENT; ++i)1315out[i] = i < QUOTIENT1316? cpp::numeric_limits<typename T::word_type>::max()1317: mask_trailing_ones<typename T::word_type, REMAINDER>();1318return out;1319}13201321// Specialization of mask_leading_ones ('math_extras.h') for BigInt.1322template <typename T, size_t count>1323LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() {1324static_assert(!T::SIGNED && count <= T::BITS);1325if (count == T::BITS)1326return T::all_ones();1327constexpr size_t QUOTIENT = (T::BITS - count - 1U) / T::WORD_SIZE;1328constexpr size_t REMAINDER = count % T::WORD_SIZE;1329T out; // zero initialized1330for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i)1331out[i] = i > QUOTIENT1332? cpp::numeric_limits<typename T::word_type>::max()1333: mask_leading_ones<typename T::word_type, REMAINDER>();1334return out;1335}13361337// Specialization of mask_trailing_zeros ('math_extras.h') for BigInt.1338template <typename T, size_t count>1339LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>1340mask_trailing_zeros() {1341return mask_leading_ones<T, T::BITS - count>();1342}13431344// Specialization of mask_leading_zeros ('math_extras.h') for BigInt.1345template <typename T, size_t count>1346LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>1347mask_leading_zeros() {1348return mask_trailing_ones<T, T::BITS - count>();1349}13501351// Specialization of count_zeros ('math_extras.h') for BigInt.1352template <typename T>1353[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1354count_zeros(T value) {1355return cpp::popcount(~value);1356}13571358// Specialization of first_leading_zero ('math_extras.h') for BigInt.1359template <typename T>1360[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1361first_leading_zero(T value) {1362return value == cpp::numeric_limits<T>::max() ? 01363: cpp::countl_one(value) + 1;1364}13651366// Specialization of first_leading_one ('math_extras.h') for BigInt.1367template <typename T>1368[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1369first_leading_one(T value) {1370return first_leading_zero(~value);1371}13721373// Specialization of first_trailing_zero ('math_extras.h') for BigInt.1374template <typename T>1375[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1376first_trailing_zero(T value) {1377return value == cpp::numeric_limits<T>::max() ? 01378: cpp::countr_zero(~value) + 1;1379}13801381// Specialization of first_trailing_one ('math_extras.h') for BigInt.1382template <typename T>1383[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1384first_trailing_one(T value) {1385return value == 0 ? 0 : cpp::countr_zero(value) + 1;1386}13871388} // namespace LIBC_NAMESPACE_DECL13891390#endif // LLVM_LIBC_SRC___SUPPORT_BIG_INT_H139113921393