22#ifndef JAU_BIG_INT_HPP_
23#define JAU_BIG_INT_HPP_
84 bn.set_word_at(1,
static_cast<mp_word_t>(n >> 32));
85 bn.set_word_at(0,
static_cast<mp_word_t>(n));
139 m_data.set_word_at(0, n);
141 m_data.set_word_at(1,
static_cast<mp_word_t>(n >> 32));
142 m_data.set_word_at(0,
static_cast<mp_word_t>(n));
157 if ( str.length() > 0 && str[0] ==
'-' ) {
162 if ( str.length() > markers + 2 && str[markers] ==
'0' &&
163 str[markers + 1] ==
'x' ) {
187 binary_decode(buf, byte_len, byte_order);
190 BigInt(std::vector<mp_word_t>&& other_reg)
noexcept {
191 this->swap_reg(other_reg);
201 if (
this != &other ) {
212 m_data.swap(other.m_data);
213 std::swap(m_signedness, other.m_signedness);
217 void swap_reg(std::vector<mp_word_t>& reg)
noexcept {
241 return m_data.get_word_at(n);
306 size_t size() const noexcept {
return m_data.size(); }
312 size_t sig_words() const noexcept {
return m_data.sig_words(); }
325 return full_words + top_bits;
333 m_data.set_to_zero();
402 m_data.set_word_at(which,
word_at(which) | mask);
438 return add(y.data(), y.sig_words(), y.sign());
446 return add2(*
this, y.data(), y.sig_words(), y.sign());
450 return add2(*
this, y.data(), y.sig_words(), y.reverse_sign());
458 const size_t bits_free = top_bits_free();
460 const size_t new_size =
size + shift_words + (bits_free < shift_bits);
462 m_data.grow_to(new_size);
473 ops::bigint_shr1(m_data.mutable_data(), m_data.size(), shift_words, shift_bits);
497 if ( shift_words >= x_sw ) {
513 std::vector<mp_word_t> ws;
514 return this->mul(y, ws);
519 const size_t y_sw = y.sig_words();
522 z.resize(
size() + y.size());
524 if ( x_sw == 1 && y_sw ) {
526 }
else if ( y_sw == 1 && x_sw ) {
528 }
else if ( x_sw && y_sw ) {
531 z.cond_flip_sign(x_sw > 0 && y_sw > 0 &&
sign() != y.sign());
537 (*this) >>= (y.
bits() - 1);
539 (*this) = (*this) / y;
549 vartime_divide(*
this, y, q, r);
557 return (*
this = (*
this) % mod);
574 vartime_divide(*
this, mod, q, r);
700 mp_word_t conversion_radix, radix_digits;
702 conversion_radix = 10000000000000000000U;
705 conversion_radix = 1000000000U;
710 const size_t digit_estimate =
static_cast<size_t>(1 + (
static_cast<double>(this->
bits()) / 3.32));
713 const size_t digit_blocks = (digit_estimate + radix_digits - 1) / radix_digits;
719 std::vector<mp_word_t> digit_groups(digit_blocks);
721 for (
size_t i = 0; i != digit_blocks; ++i ) {
723 ct_divide_word(
value, conversion_radix,
value, remainder);
724 digit_groups[i] = remainder;
726 assert(
value.is_zero());
729 std::vector<uint8_t>
digits(digit_blocks * radix_digits);
731 for (
size_t i = 0; i != digit_blocks; ++i ) {
733 for (
size_t j = 0; j != radix_digits; ++j ) {
737 digits[radix_digits * i + j] =
static_cast<uint8_t
>(digit);
746 assert(digit_estimate >=
digits.size());
750 s.reserve(1 +
digits.size());
757 for ( uint8_t d :
digits ) {
758 s.push_back(
static_cast<char>(d +
'0'));
771 std::vector<uint8_t>
bits;
778 data_len =
bits.size();
780 data =
reinterpret_cast<const uint8_t*
>(m_data.const_data());
799 : m_reg(), m_sig_words(sig_words_npos) { }
801 data_t(
const data_t& o)
noexcept =
default;
803 data_t(data_t&& o)
noexcept {
806 data_t(std::vector<mp_word_t>&& reg)
noexcept {
810 ~data_t() noexcept = default;
812 data_t& operator=(const data_t& r) noexcept = default;
814 data_t& operator=(data_t&& other) noexcept {
815 if (
this != &other ) {
820 data_t& operator=(std::vector<mp_word_t>&& other_reg)
noexcept {
821 if ( &m_reg != &other_reg ) {
822 this->swap(other_reg);
828 invalidate_sig_words();
832 const mp_word_t* const_data() const noexcept {
836 std::vector<mp_word_t>& mutable_vector() noexcept {
837 invalidate_sig_words();
841 const std::vector<mp_word_t>& const_vector() const noexcept {
845 mp_word_t get_word_at(
size_t n)
const noexcept {
846 if ( n < m_reg.size() ) {
852 void set_word_at(
size_t i,
mp_word_t w) {
853 invalidate_sig_words();
854 if ( i >= m_reg.size() ) {
863 void set_words(
const mp_word_t w[],
size_t len) {
864 invalidate_sig_words();
865 m_reg.assign(w, w + len);
869 m_reg.resize(m_reg.capacity());
870 clear_mem(m_reg.data(), m_reg.size());
874 void set_size(
size_t s) {
875 invalidate_sig_words();
876 clear_mem(m_reg.data(), m_reg.size());
877 m_reg.resize(s + (8 - (s % 8)));
880 void mask_bits(
size_t n)
noexcept {
881 if ( n == 0 ) {
return set_to_zero(); }
886 if ( top_word < size() ) {
888 const size_t len = size() - (top_word + 1);
890 clear_mem(&m_reg[top_word + 1], len);
892 m_reg[top_word] &= mask;
893 invalidate_sig_words();
897 void grow_to(
size_t n)
const {
899 if ( n <= m_reg.capacity() ) {
902 m_reg.resize(n + (8 - (n % 8)));
907 size_t size() const noexcept {
return m_reg.size(); }
909 void shrink_to_fit(
size_t min_size = 0) {
910 const size_t words = std::max(min_size, sig_words());
914 void resize(
size_t s) {
918 void swap(data_t& other)
noexcept {
919 m_reg.swap(other.m_reg);
920 std::swap(m_sig_words, other.m_sig_words);
923 void swap(std::vector<mp_word_t>& reg)
noexcept {
925 invalidate_sig_words();
928 void invalidate_sig_words() const noexcept {
929 m_sig_words = sig_words_npos;
932 size_t sig_words() const noexcept {
933 if ( m_sig_words == sig_words_npos ) {
934 m_sig_words = calc_sig_words();
936 assert(m_sig_words == calc_sig_words());
942 static const size_t sig_words_npos =
static_cast<size_t>(-1);
944 size_t calc_sig_words() const noexcept {
945 const size_t sz = m_reg.size();
950 for (
size_t i = 0; i != sz; ++i ) {
965 mutable std::vector<mp_word_t> m_reg;
966 mutable size_t m_sig_words = sig_words_npos;
978 static constexpr uint8_t get_byte_var_be(
size_t byte_num, T input)
noexcept {
979 return static_cast<uint8_t
>(input >> (((~byte_num) & (
sizeof(T) - 1)) << 3));
988 static constexpr uint8_t get_byte_var_le(
size_t byte_num, T input)
noexcept {
989 return static_cast<uint8_t
>(input >> (byte_num << 3));
1000 static constexpr void clear_bytes(
void* ptr,
size_t bytes)
noexcept {
1002 std::memset(ptr, 0,
bytes);
1016 template<
typename T>
1017 static constexpr void clear_mem(T* ptr,
size_t n)
noexcept {
1018 clear_bytes(ptr,
sizeof(T) * n);
1025 void grow_to(
size_t n)
const { m_data.grow_to(n); }
1027 void resize(
size_t s) { m_data.resize(s); }
1029 void set_word_at(
size_t i,
mp_word_t w) {
1030 m_data.set_word_at(i, w);
1033 void set_words(
const mp_word_t w[],
size_t len) {
1034 m_data.set_words(w, len);
1040 mp_word_t* mutable_data() {
return m_data.mutable_data(); }
1048 void binary_decode(
const uint8_t buf[],
size_t byte_len,
const lb_endian_t byte_order) {
1049 const size_t full_words = byte_len /
sizeof(
mp_word_t);
1050 const size_t extra_bytes = byte_len %
sizeof(
mp_word_t);
1054 m_data.set_size(
jau::round_up(full_words + (extra_bytes > 0 ? 1U : 0U), 8U));
1056 mp_word_t* sink = m_data.mutable_data();
1059 for (
size_t i = 0; i < full_words; ++i ) {
1064 for (
size_t i = 0; i < full_words; ++i ) {
1070 for (
size_t i = 0; i < extra_bytes; ++i ) {
1074 for (
size_t i = 0; i < extra_bytes; ++i ) {
1087 static BigInt hex_decode(
const uint8_t buf[],
size_t str_len,
const lb_endian_t byte_order) {
1090 std::vector<uint8_t> bin_out;
1093 throw jau::math::MathDomainError(
"invalid hexadecimal char @ " + std::to_string(str_len2) +
"/" + std::to_string(str_len) +
" of '" +
1101 static BigInt dec_decode(
const uint8_t buf[],
size_t str_len) {
1105 for (
size_t i = 0; i < str_len; ++i ) {
1106 const char c =
static_cast<char>(buf[i]);
1108 if ( c <
'0' || c >
'9' ) {
1109 throw jau::math::MathDomainError(
"invalid decimal char",
E_FILE_LINE);
1111 const uint8_t x = c -
'0';
1135 const size_t full_words = byte_len /
sizeof(
mp_word_t);
1136 const size_t extra_bytes = byte_len %
sizeof(
mp_word_t);
1140 for (
size_t i = 0; i < full_words; ++i ) {
1145 for (
size_t i = 0; i < full_words; ++i ) {
1149 if ( extra_bytes > 0 ) {
1152 for (
size_t i = 0; i < extra_bytes; ++i ) {
1153 output[full_words *
sizeof(
mp_word_t) + i] = get_byte_var_le(i, le_w);
1156 for (
size_t i = 0; i < extra_bytes; ++i ) {
1157 output[extra_bytes - 1 - i] = get_byte_var_le(i, le_w);
1161 return extra_bytes + full_words *
sizeof(
mp_word_t);
1165 size_t top_bits_free() const noexcept {
1181 int cmp(
const BigInt& other,
bool check_signs =
true) const noexcept {
1182 if ( check_signs ) {
1183 if ( other.is_positive() && this->is_negative() ) {
1186 if ( other.is_negative() && this->is_positive() ) {
1189 if ( other.is_negative() && this->is_negative() ) {
1191 other.data(), other.size()));
1195 other.data(), other.size());
1198 bool is_equal(
const BigInt& other)
const noexcept {
1199 if ( this->
sign() != other.sign() ) {
1203 other.data(), other.sig_words())
1207 bool is_less_than(
const BigInt& other)
const noexcept {
1208 if ( this->
is_negative() && other.is_positive() ) {
1211 if ( this->
is_positive() && other.is_negative() ) {
1214 if ( other.is_negative() && this->is_negative() ) {
1216 this->data(), this->sig_words())
1220 other.data(), other.sig_words())
1226 grow_to(std::max(x_sw, y_words) + 1);
1228 if (
sign() == y_sign ) {
1233 if ( relative_size >= 0 ) {
1241 if ( relative_size < 0 ) {
1243 }
else if ( relative_size == 0 ) {
1258 const size_t x_sw = x.sig_words();
1262 if ( x.sign() == y_sign ) {
1264 z.set_sign(x.sign());
1266 const int32_t relative_size =
ops::bigint_sub_abs(
z.mutable_data(), x.data(), x_sw, y, y_words);
1269 if ( relative_size < 0 ) {
1271 }
else if ( relative_size == 0 ) {
1274 z.set_sign(x.sign());
1280 BigInt& mul(
const BigInt& y, std::vector<mp_word_t>& ws)
noexcept {
1282 const size_t y_sw = y.sig_words();
1285 if ( x_sw == 0 || y_sw == 0 ) {
1288 }
else if ( x_sw == 1 && y_sw ) {
1291 }
else if ( y_sw == 1 && x_sw ) {
1293 set_word_at(x_sw, carry);
1295 const size_t new_size = x_sw + y_sw + 1;
1298 std::vector<mp_word_t> z_reg(new_size);
1302 this->swap_reg(z_reg);
1319 void cond_flip_sign(
bool predicate)
noexcept {
1322 const uint8_t current_sign =
static_cast<uint8_t
>(
sign());
1323 const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
1334 inline size_t reduce_below(
const BigInt& p, std::vector<mp_word_t>& ws) {
1335 if ( p.is_negative() || this->is_negative() ) {
1337 if ( p.is_negative() ) {
1338 msg.append(
"p < 0");
1341 if ( msg.length() > 0 ) {
1342 msg.append(
" and ");
1344 msg.append(
"*this < 0");
1346 throw jau::math::MathDomainError(msg,
E_FILE_LINE);
1348 const size_t p_words = p.sig_words();
1350 if (
size() < p_words + 1 ) {
1351 grow_to(p_words + 1);
1353 if ( ws.size() < p_words + 1 ) {
1354 ws.resize(p_words + 1);
1356 clear_mem(ws.data(), ws.size());
1358 size_t reductions = 0;
1372 q.cond_flip_sign(x.sign() != y.sign());
1374 if ( x.is_negative() && r.is_nonzero() ) {
1403 if ( y_arg.is_zero() ) {
1404 throw jau::math::MathDivByZeroError(
"y_arg == 0",
E_FILE_LINE);
1406 const size_t y_words = y_arg.sig_words();
1408 assert(y_words > 0);
1414 std::vector<mp_word_t> ws;
1420 const size_t shifts = y.top_bits_free();
1426 const size_t t = y_words - 1;
1427 const size_t n = std::max(y_words, r.sig_words()) - 1;
1430 q.grow_to(n - t + 1);
1437 q_words[n -
t] = r.reduce_below(shifted_y, ws);
1440 const mp_word_t y_t1 = y.word_at(t - 1);
1443 for (
size_t j = n;
j !=
t; --
j ) {
1445 const mp_word_t x_j1 = r.word_at(j - 1);
1446 const mp_word_t x_j2 = r.word_at(j - 2);
1453 qjt -= division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2);
1454 qjt -= division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2);
1455 assert(division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2) ==
false);
1461 r -= shifted_y * qjt;
1462 qjt -= r.is_negative();
1463 r += shifted_y *
static_cast<mp_word_t>(r.is_negative());
1465 q_words[
j -
t - 1] = qjt;
1470 sign_fixup(x, y_arg, q, r);
1478 throw jau::math::MathDivByZeroError(
"y == 0",
E_FILE_LINE);
1482 ct_divide_word(*
this, y, q, r);
1488 throw jau::math::MathDivByZeroError(
"y == 0",
E_FILE_LINE);
1490 const size_t x_words = x.sig_words();
1491 const size_t x_bits = x.bits();
1496 for (
size_t i = 0; i != x_bits; ++i ) {
1497 const size_t b = x_bits - 1 - i;
1498 const bool x_b = x.get_bit(b);
1506 q.conditionally_set_bit(b, r_gte_y.is_set());
1507 r = r_gte_y.select(r - y, r);
1510 if ( x.is_negative() ) {
1524 throw jau::math::MathDivByZeroError(
"mod == 0",
E_FILE_LINE);
1532 remainder = (
word_at(0) & (mod - 1));
1535 for (
size_t i = sw; i > 0; --i ) {
1540 return mod - remainder;
1545 void append_detail(std::string& s)
const noexcept {
1546 s.append(
", bits ").append(std::to_string(
bits())).append(
", ").append(std::to_string(
sig_words())).append(
" word(s): ");
1547 for (
size_t i = 0; i <
sig_words(); ++i ) {
1569 return x < y ? x : y;
1572 return x > y ? x : y;
1575 return min(
max(x, min_val), max_val);
1579 return x < y ? x : y;
1582 return x > y ? x : y;
1585 return min(
max(x, min_val), max_val);
static Mask< T > is_gte(T x, T y) noexcept
Return a Mask<T> which is set if x >= y.
static Mask< T > is_equal(T x, T y) noexcept
Return a Mask<T> which is set if x == y.
static Mask< T > expand(T v) noexcept
Return a Mask<T> which is set if v is != 0.
math_error_t::div_by_zero, i.e.
Arbitrary precision integer type.
BigInt & set_sign(sign_t sign) noexcept
Set sign of the integer.
BigInt(uint64_t n)
Create big_int_t from an unsigned 64 bit integer.
bool is_even() const noexcept
Test if the integer has an even value.
size_t bits() const noexcept
Returns bit length of this integer.
std::string to_dec_string(bool add_details=false) const
bool operator==(const BigInt &b) const noexcept
bool is_odd() const noexcept
Test if the integer has an odd value.
bool get_bit(size_t n) const noexcept
Return bit value at specified position.
BigInt & operator-=(const BigInt &y) noexcept
BigInt abs() const noexcept
Returns absolute (positive) value of this instance.
BigInt & operator++() noexcept
std::strong_ordering operator<=>(const BigInt& b) const noexcept { const int r = cmp(b); return 0 == ...
BigInt operator-() const noexcept
Unary negation operator, returns new negative instance of this.
BigInt & mod_add(const BigInt &y, const BigInt &mod, std::vector< mp_word_t > &ws)
Set *this to (*this + y) % mod This function assumes *this is >= 0 && < mod.
BigInt pow(BigInt e)
Returns (*this)^e, or pow(*this, e)
BigInt & operator--() noexcept
size_t bytes() const
Returns byte length of this integer.
BigInt & operator<<=(size_t shift) noexcept
BigInt(const uint8_t buf[], size_t byte_len, const lb_endian_t byte_order)
Create a big_int_t from an integer in a byte array with given byte_len, considering the given byte_or...
BigInt & operator=(const BigInt &r)=default
BigInt operator>>(size_t shift) const
std::string to_hex_string(bool add_details=false) const noexcept
BigInt operator--(int) noexcept
sign_t reverse_sign() const noexcept
bool operator<=(const BigInt &b) const noexcept
BigInt operator+(const BigInt &y) const noexcept
sign_t
Sign symbol definitions for positive and negative numbers.
BigInt operator%(const BigInt &mod)
bool operator>(const BigInt &b) const noexcept
const mp_word_t * data() const
Return a const pointer to the register.
bool is_nonzero() const noexcept
Test if the integer is not zero.
size_t size() const noexcept
Give size of internal register.
static BigInt one()
Create a 1-value big_int.
sign_t sign() const noexcept
Return the sign of the integer.
bool is_negative() const noexcept
Tests if the sign of the integer is negative.
BigInt & operator>>=(size_t shift) noexcept
BigInt & rev_sub(const BigInt &y, std::vector< mp_word_t > &ws)
Set *this to y - *this.
BigInt & operator=(BigInt &&other) noexcept
static BigInt zero()
Create a 0-value big_int.
void conditionally_set_bit(size_t n, bool set_it) noexcept
Conditionally set bit at specified position.
size_t sig_words() const noexcept
Return how many words we need to hold this value.
void clear()
Zeroize the big_int.
BigInt(std::vector< mp_word_t > &&other_reg) noexcept
BigInt() noexcept=default
BigInt & operator%=(const BigInt &mod)
Modulo operator.
bool operator!() const noexcept
!
BigInt & mod_sub(const BigInt &y, const BigInt &mod, std::vector< mp_word_t > &ws)
Set *this to (*this - y) % mod This function assumes *this is >= 0 && < mod.
bool is_positive() const noexcept
Tests if the sign of the integer is positive.
bool operator<(const BigInt &b) const noexcept
bool operator!=(const BigInt &b) const noexcept
bool operator>=(const BigInt &b) const noexcept
size_t binary_encode(uint8_t output[], size_t byte_len, const lb_endian_t byte_order) const noexcept
Stores this number to the value in buf with given byte_len, considering the given byte_order.
void swap(BigInt &other) noexcept
Swap this value with another.
int compare(const BigInt &b) const noexcept
Compares this instance against other considering both sign() value Returns.
static BigInt from_s32(int32_t n)
Create big_int from a signed 32 bit integer.
BigInt & square(std::vector< mp_word_t > &ws)
Square value of *this.
BigInt & operator/=(const BigInt &y)
static BigInt from_word(mp_word_t n)
Create big_int from a mp_word_t (limb)
static BigInt with_capacity(size_t n)
Create big_int of specified size, all zeros.
bool is_zero() const noexcept
Test if the integer is zero.
mp_word_t word_at(size_t n) const noexcept
Return the mp_word_t at a specified position of the internal register.
BigInt operator/(const BigInt &y) const
BigInt operator-(const BigInt &y) const noexcept
BigInt & operator*=(const BigInt &y) noexcept
BigInt & mod_mul(uint8_t y, const BigInt &mod, std::vector< mp_word_t > &ws)
Set *this to (*this * y) % mod This function assumes *this is >= 0 && < mod y should be small,...
uint8_t byte_at(size_t n) const noexcept
BigInt mod_pow(BigInt e, const BigInt &m)
Returns (*this)^e % m, or pow(*this, e) % m.
BigInt & flip_sign() noexcept
Flip the sign of this big_int.
BigInt & operator+=(const BigInt &y) noexcept
void set_bit(size_t n) noexcept
Set bit at specified position.
BigInt operator*(const BigInt &y) noexcept
BigInt operator<<(size_t shift) const
BigInt(const std::string &str)
Construct a big_int_t from a string encoded as hexadecimal or decimal.
static BigInt from_u64(uint64_t n)
Create big_int from an unsigned 64 bit integer.
BigInt operator++(int) noexcept
BigInt(BigInt &&other) noexcept
static BigInt power_of_2(size_t n)
Create a power of two.
constexpr bool is_little_endian() noexcept
Evaluates true if platform is running in little endian mode, i.e.
constexpr std::enable_if_t< std::is_standard_layout_v< T >, T > get_value(uint8_t const *buffer) noexcept
Returns a T value from the given byte address using packed_t to resolve a potential memory alignment ...
char * cast_uint8_ptr_to_char(uint8_t *b) noexcept
constexpr uint16_t le_to_cpu(uint16_t const l) noexcept
lb_endian_t
Simplified reduced endian type only covering little- and big-endian.
constexpr std::enable_if_t< std::is_standard_layout_v< T >, void > put_value(uint8_t *buffer, const T &v) noexcept
Put the given T value into the given byte address using packed_t to resolve a potential memory alignm...
constexpr uint16_t cpu_to_le(uint16_t const h) noexcept
const uint8_t * cast_char_ptr_to_uint8(const char *s) noexcept
@ little
Identifier for little endian, equivalent to endian::little.
@ big
Identifier for big endian, equivalent to endian::big.
constexpr T ct_is_zero(T x)
Returns ~0 (2-complement) if arg is zero, otherwise 0 (w/o branching) in O(1) and constant time (CT).
constexpr bool value(const Bool rhs) noexcept
constexpr Bool False() noexcept
void swap(cow_darray< Value_type, Size_type, Alloc_type > &rhs, cow_darray< Value_type, Size_type, Alloc_type > &lhs) noexcept
constexpr T clamp(const T x, const T min_val, const T max_val) noexcept
Returns constrained integral value to lie between given min- and maximum value (w/ branching) in O(1)...
constexpr T round_up(const T n, const U align_to)
Round up w/ branching in O(1)
constexpr nsize_t high_bit(T x)
Return the index of the highest set bit w/ branching (loop) in O(n/2).
constexpr size_t digits(const T x, const nsize_t radix) noexcept
Returns the number of digits of the given unsigned integral value number and the given radix.
constexpr T gcd(T a, T b) noexcept
Returns the greatest common divisor (GCD) of the two given integer values following Euclid's algorith...
mp::BigInt pow(mp::BigInt b, const mp::BigInt &e)
constexpr bool is_power_of_2(const T x) noexcept
Power of 2 test in O(1), i.e.
constexpr T min(const T x, const T y) noexcept
Returns the minimum of two integrals (w/ branching) in O(1)
constexpr T max(const T x, const T y) noexcept
Returns the maximum of two integrals (w/ branching) in O(1)
constexpr T abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/ branching) in O(1)
SizeBoolPair fromHexString(std::vector< uint8_t > &out, const uint8_t hexstr[], const size_t hexstr_len, const lb_endian_t byteOrder=lb_endian_t::big, const Bool checkPrefix=Bool::True) noexcept
Converts a given hexadecimal string representation into a byte vector, lsb-first.
std::string toHexString(const void *data, const nsize_t length, const lb_endian_t byteOrder=lb_endian_t::big, const LoUpCase capitalization=LoUpCase::lower, const PrefixOpt prefix=PrefixOpt::prefix) noexcept
Produce a hexadecimal string representation of the given lsb-first byte values.
void unpoison(const T *p, size_t n)
CT::Mask< mp_word_t > bigint_ct_is_lt(const mp_word_t x[], size_t x_size, const mp_word_t y[], size_t y_size, bool lt_or_equal=false) noexcept
Compare x and y Return ~0 if x[0:x_size] < y[0:y_size] or 0 otherwise If lt_or_equal is true,...
CT::Mask< mp_word_t > bigint_ct_is_eq(const mp_word_t x[], size_t x_size, const mp_word_t y[], size_t y_size) noexcept
int bigint_cmp(const mp_word_t x[], size_t x_size, const mp_word_t y[], size_t y_size) noexcept
Compare unsigned x and y mp_word_t.
mp_word_t bigint_divop(mp_word_t n1, mp_word_t n0, mp_word_t d)
Computes ((n1<<bits) + n0) / d.
int32_t bigint_sub_abs(mp_word_t z[], const mp_word_t x[], size_t x_size, const mp_word_t y[], size_t y_size) noexcept
Set z to abs(x-y), ie if x >= y, then compute z = x - y Otherwise compute z = y - x No borrow is poss...
mp_word_t bigint_add2(mp_word_t x[], size_t x_size, const mp_word_t y[], size_t y_size) noexcept
Two operand addition with carry out.
void bigint_shr1(mp_word_t x[], size_t x_size, size_t word_shift, size_t bit_shift) noexcept
mp_word_t bigint_linmul2(mp_word_t x[], size_t x_size, mp_word_t y) noexcept
void bigint_linmul3(mp_word_t z[], const mp_word_t x[], size_t x_size, mp_word_t y) noexcept
mp_word_t bigint_sub3(mp_word_t z[], const mp_word_t x[], size_t x_size, const mp_word_t y[], size_t y_size) noexcept
Three operand subtraction.
void bigint_shl2(mp_word_t y[], const mp_word_t x[], size_t x_size, size_t word_shift, size_t bit_shift) noexcept
void bigint_add3(mp_word_t z[], const mp_word_t x[], size_t x_size, const mp_word_t y[], size_t y_size) noexcept
Three operand addition.
mp_word_t bigint_sub2(mp_word_t x[], size_t x_size, const mp_word_t y[], size_t y_size) noexcept
Two operand subtraction.
mp_word_t bigint_modop(mp_word_t n1, mp_word_t n0, mp_word_t d)
Compute ((n1<<bits) + n0) % d.
mp_word_t word_madd2(mp_word_t a, mp_word_t b, mp_word_t &c) noexcept
Word Multiply/Add.
void bigint_shl1(mp_word_t x[], size_t x_size, size_t x_words, size_t word_shift, size_t bit_shift) noexcept
void basecase_mul(mp_word_t z[], size_t z_size, const mp_word_t x[], size_t x_size, const mp_word_t y[], size_t y_size) noexcept
void bigint_shr2(mp_word_t y[], const mp_word_t x[], size_t x_size, size_t word_shift, size_t bit_shift) noexcept
void bigint_sub2_rev(mp_word_t x[], const mp_word_t y[], size_t y_size) noexcept
Two operand subtraction, x = y - x; assumes y >= x.
big_int_t (this file) (c) 2024 Gothel Software e.K.
jau::uint_bytes< impl::best_word_byte_size()>::type mp_word_t
constexpr const size_t mp_word_bits
constexpr const mp_word_t mp_word_max
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
std::ostream & operator<<(std::ostream &os, const jau::fraction_timespec &v) noexcept
Output stream operator for jau::fraction_timespec.