24 using digit_type = DigitType;
25 using signed_digit_type = std::make_signed_t<digit_type>;
26 static constexpr auto num_digits = NumDigits;
27 static constexpr auto is_signed = IsSigned;
28 static constexpr auto bits_per_digit =
sizeof(digit_type) * CHAR_BIT;
30 static constexpr digit_type zero_digit = 0;
31 static constexpr digit_type min1_digit =
static_cast<digit_type
>(signed_digit_type{-1});
41 for (
size_t i = 0; i != num_digits; ++i) {
47 constexpr bigint &operator=(
bigint const &)
noexcept =
default;
49 constexpr
bigint &operator=(
bigint &&) noexcept = default;
53 template<
size_t N,
bool S>
54 constexpr
bigint(
bigint<digit_type, N, S> const &rhs) noexcept requires(N < num_digits)
64 ttlet sign = rhs.is_negative() ? min1_digit : zero_digit;
65 for (; i != num_digits; ++i) {
72 template<
size_t N,
bool S>
83 ttlet sign = rhs.is_negative() ? min1_digit : zero_digit;
84 for (; i != num_digits; ++i) {
90 constexpr bigint(std::integral
auto value)
noexcept
92 static_assert(
sizeof(value) <=
sizeof(digit_type));
93 static_assert(num_digits > 0);
95 if constexpr (std::is_signed_v<
decltype(value)>) {
97 digits[0] =
static_cast<digit_type
>(
static_cast<signed_digit_type
>(value));
99 digits[0] =
static_cast<digit_type
>(value);
103 ttlet sign = value < 0 ? min1_digit : zero_digit;
104 for (
size_t i = 1; i != num_digits; ++i) {
109 constexpr bigint &operator=(std::integral
auto value)
noexcept
111 static_assert(
sizeof(value) <=
sizeof(digit_type));
112 static_assert(num_digits > 0);
114 if constexpr (std::is_signed_v<
decltype(value)>) {
116 digits[0] =
static_cast<digit_type
>(
static_cast<signed_digit_type
>(value));
118 digits[0] =
static_cast<digit_type
>(value);
122 ttlet sign = value < 0 ? min1_digit : zero_digit;
123 for (
size_t i = 1; i != num_digits; ++i) {
129 constexpr explicit bigint(std::string_view str,
int base = 10) noexcept :
bigint()
132 for (; i < str.size(); ++i) {
134 (*this) += base16::int_from_char<int>(str[i]);
138 constexpr explicit operator unsigned long long() const noexcept
140 return static_cast<unsigned long long>(
digits[0]);
142 constexpr explicit operator signed long long() const noexcept
144 return static_cast<signed long long>(
digits[0]);
146 constexpr explicit operator unsigned long() const noexcept
148 return static_cast<unsigned long>(
digits[0]);
150 constexpr explicit operator signed long() const noexcept
152 return static_cast<signed long>(
digits[0]);
154 constexpr explicit operator unsigned int() const noexcept
156 return static_cast<unsigned int>(
digits[0]);
158 constexpr explicit operator signed int() const noexcept
160 return static_cast<signed int>(
digits[0]);
162 constexpr explicit operator unsigned short() const noexcept
164 return static_cast<unsigned short>(
digits[0]);
166 constexpr explicit operator signed short() const noexcept
168 return static_cast<signed short>(
digits[0]);
170 constexpr explicit operator unsigned char() const noexcept
172 return static_cast<unsigned char>(
digits[0]);
174 constexpr explicit operator signed char() const noexcept
176 return static_cast<signed char>(
digits[0]);
179 constexpr explicit operator bool() const noexcept
181 for (
size_t i = 0; i != num_digits; ++i) {
189 [[nodiscard]]
constexpr bool is_negative() const noexcept
191 if constexpr (is_signed and num_digits > 0) {
192 return static_cast<signed_digit_type
>(
digits[num_digits - 1]) < 0;
198 template<
size_t N,
bool S>
199 constexpr explicit operator bigint<digit_type, N, S>() const noexcept
201 auto r = bigint<digit_type, N, S>{};
203 ttlet sign = is_negative() ? min1_digit : zero_digit;
204 for (
auto i = 0; i != N; ++i) {
205 r.digits[i] = i < num_digits ?
digits[i] : sign;
212 constexpr auto oneOver10 =
reciprocal(bigint<digit_type, num_digits * 2, is_signed>{10});
224 r += (
static_cast<unsigned char>(
remainder) +
'0');
235 std::is_same_v<digit_type, uint64_t> && num_digits == 2,
236 "uuid_string should only be called on a uuid compatible type");
238 "{:08x}-{:04x}-{:04x}-{:04x}-{:012x}",
239 static_cast<uint32_t
>(
digits[1] >> 32),
240 static_cast<uint16_t
>(
digits[1] >> 16),
241 static_cast<uint16_t
>(
digits[1]),
242 static_cast<uint16_t
>(
digits[0] >> 48),
243 digits[0] & 0x0000ffff'ffffffffULL);
246 [[nodiscard]]
constexpr bigint operator-() const noexcept
249 neg_carry_chain(r.digits,
digits, num_digits);
253 constexpr bigint &operator<<=(
size_t rhs)
noexcept
259 constexpr bigint &operator>>=(
size_t rhs)
noexcept
261 if constexpr (is_signed) {
269 constexpr bigint &operator*=(
bigint const &rhs)
noexcept
272 mul_carry_chain(r.digits,
digits, rhs.digits, num_digits);
277 constexpr bigint &operator+=(
bigint const &rhs)
noexcept
279 add_carry_chain(
digits,
digits, rhs.digits, num_digits);
283 constexpr bigint &operator-=(
bigint const &rhs)
noexcept
285 sub_carry_chain(
digits,
digits, rhs.digits, num_digits);
289 constexpr bigint &operator&=(
bigint const &rhs)
noexcept
291 and_carry_chain(
digits,
digits, rhs.digits, num_digits);
295 constexpr bigint &operator|=(
bigint const &rhs)
noexcept
301 constexpr bigint &operator^=(
bigint const &rhs)
noexcept
303 xor_carry_chain(
digits,
digits, rhs.digits, num_digits);
307 static bigint from_big_endian(uint8_t
const *data)
noexcept
310 for (ssize_t i =
static_cast<ssize_t
>(num_digits) - 1; i >= 0; i--) {
312 for (
size_t j = 0; j <
sizeof(digit_type); j++) {
321 static bigint from_little_endian(uint8_t
const *data)
noexcept
324 for (
int i = 0; i < num_digits; ++i) {
326 for (
size_t j = 0; j <
sizeof(digit_type); j++) {
327 d |=
static_cast<digit_type
>(*(data++)) << (j * 8);
334 static bigint from_big_endian(
void const *data)
noexcept
336 return from_big_endian(
static_cast<uint8_t
const *
>(data));
339 static bigint from_little_endian(
void const *data)
noexcept
341 return from_little_endian(
static_cast<uint8_t
const *
>(data));
351 ttlet polynomialOrder = bsr_carry_chain(rhs.digits, rhs.num_digits);
352 tt_assert(polynomialOrder >= 0);
357 auto tmp_highest_bit = bsr_carry_chain(tmp.digits, tmp.num_digits);
358 while (tmp_highest_bit >= polynomialOrder) {
359 ttlet divident = rhs_ << (tmp_highest_bit - polynomialOrder);
362 tmp_highest_bit = bsr_carry_chain(tmp.digits, tmp.num_digits);
365 return static_cast<bigint>(tmp);
378 r.digits[num_digits] = 1;
379 return static_cast<bigint>(r / rhs);
382 [[nodiscard]]
constexpr friend bool operator==(
bigint const &lhs,
bigint const &rhs)
noexcept
384 return eq_carry_chain(lhs.digits, rhs.digits, lhs.num_digits);
387 [[nodiscard]]
constexpr friend std::strong_ordering operator<=>(
bigint const &lhs,
bigint const &rhs)
noexcept
389 if constexpr (lhs.is_signed or rhs.is_signed) {
390 return cmp_signed_carry_chain(lhs.digits, rhs.digits, lhs.num_digits);
392 return cmp_unsigned_carry_chain(lhs.digits, rhs.digits, lhs.num_digits);
396 [[nodiscard]]
constexpr friend bigint operator<<(
bigint const &lhs,
size_t rhs)
noexcept
399 sll_carry_chain(r.digits, lhs.digits, rhs, lhs.num_digits);
403 [[nodiscard]]
constexpr friend bigint operator>>(
bigint const &lhs,
size_t rhs)
noexcept
406 if constexpr (lhs.is_signed) {
407 sra_carry_chain(r.digits, lhs.digits, rhs, lhs.num_digits);
409 srl_carry_chain(r.digits, lhs.digits, rhs, lhs.num_digits);
414 [[nodiscard]]
constexpr friend bigint operator*(
bigint const &lhs,
bigint const &rhs)
noexcept
417 mul_carry_chain(r.digits, lhs.digits, rhs.digits, lhs.num_digits);
421 [[nodiscard]]
constexpr friend bigint operator+(
bigint const &lhs,
bigint const &rhs)
noexcept
424 add_carry_chain(r.digits, lhs.digits, rhs.digits, lhs.num_digits);
428 [[nodiscard]]
constexpr friend bigint operator-(
bigint const &lhs,
bigint const &rhs)
noexcept
431 sub_carry_chain(r.digits, lhs.digits, rhs.digits, lhs.num_digits);
435 [[nodiscard]]
constexpr friend bigint operator~(
bigint const &rhs)
noexcept
438 invert_carry_chain(r.digits, rhs.digits, rhs.num_digits);
442 [[nodiscard]]
constexpr friend bigint operator|(
bigint const &lhs,
bigint const &rhs)
noexcept
445 or_carry_chain(r.digits, lhs.digits, rhs.digits, lhs.num_digits);
449 [[nodiscard]]
constexpr friend bigint operator&(
bigint const &lhs,
bigint const &rhs)
noexcept
452 and_carry_chain(r.digits, lhs.digits, rhs.digits, lhs.num_digits);
456 [[nodiscard]]
constexpr friend bigint operator^(
bigint const &lhs,
bigint const &rhs)
noexcept
459 xor_carry_chain(r.digits, lhs.digits, rhs.digits, lhs.num_digits);
468 if constexpr (is_signed) {
469 signed_div_carry_chain(quotient.digits,
remainder.digits, lhs.digits, rhs.digits, lhs.num_digits);
471 div_carry_chain(quotient.digits,
remainder.digits, lhs.digits, rhs.digits, lhs.num_digits);
477 div(
bigint const &lhs,
bigint const &rhs, bigint<digit_type, 2 * num_digits, is_signed>
const &rhs_reciprocal)
noexcept
478 requires(not is_signed)
480 constexpr auto nr_bits = num_digits * bits_per_digit;
482 using bigint_x3_type = bigint<digit_type, 3 * num_digits, is_signed>;
484 auto quotient = bigint_x3_type{lhs} * bigint_x3_type{rhs_reciprocal};
485 quotient >>= (2 * nr_bits);
487 auto product = bigint_x3_type{quotient} * bigint_x3_type{rhs};
489 tt_axiom(product <= lhs);
493 while (remainder >= rhs) {
495 return div(lhs, rhs);
504 [[nodiscard]]
constexpr friend bigint operator/(
bigint const &lhs,
bigint const &rhs)
noexcept
509 if constexpr (is_signed) {
510 signed_div_carry_chain(quotient.digits,
remainder.digits, lhs.digits, rhs.digits, lhs.num_digits);
512 div_carry_chain(quotient.digits,
remainder.digits, lhs.digits, rhs.digits, lhs.num_digits);
517 [[nodiscard]]
constexpr friend bigint operator%(
bigint const &lhs,
bigint const &rhs)
noexcept
522 if constexpr (is_signed) {
523 signed_div_carry_chain(quotient.digits,
remainder.digits, lhs.digits, rhs.digits, lhs.num_digits);
525 div_carry_chain(quotient.digits,
remainder.digits, lhs.digits, rhs.digits, lhs.num_digits);
532 return lhs << rhs.string();