16#ifndef JAU_BIG_INT_HPP_
17#define JAU_BIG_INT_HPP_
76 bn.set_word_at(1,
static_cast<mp_word_t>(n >> 32));
77 bn.set_word_at(0,
static_cast<mp_word_t>(n));
131 m_data.set_word_at(0, n);
133 m_data.set_word_at(1,
static_cast<mp_word_t>(n >> 32));
134 m_data.set_word_at(0,
static_cast<mp_word_t>(n));
149 if(str.length() > 0 && str[0] ==
'-')
155 if(str.length() > markers + 2 && str[markers ] ==
'0' &&
156 str[markers + 1] ==
'x')
179 binary_decode(buf, byte_len, byte_order);
182 BigInt(std::vector<mp_word_t>&& other_reg)
noexcept {
183 this->swap_reg(other_reg);
204 m_data.swap(other.m_data);
205 std::swap(m_signedness, other.m_signedness);
209 void swap_reg(std::vector<mp_word_t>& reg)
noexcept {
233 return m_data.get_word_at(n);
298 size_t size() const noexcept {
return m_data.size(); }
304 size_t sig_words() const noexcept {
return m_data.sig_words(); }
317 return full_words + top_bits;
391 m_data.set_word_at(which,
word_at(which) | mask);
404 std::strong_ordering operator<=>(
const big_int_t& b)
const noexcept {
405 const int r = cmp(b);
406 return 0 == r ? std::strong_ordering::equal : ( 0 > r ? std::strong_ordering::less : std::strong_ordering::greater);
419 return add(y.data(), y.sig_words(), y.sign());
427 return add2(*
this, y.data(), y.sig_words(), y.sign());
431 return add2(*
this, y.data(), y.sig_words(), y.reverse_sign());
439 const size_t bits_free = top_bits_free();
441 const size_t new_size =
size + shift_words + (bits_free < shift_bits);
443 m_data.grow_to(new_size);
454 ops::bigint_shr1(m_data.mutable_data(), m_data.size(), shift_words, shift_bits);
478 if(shift_words >= x_sw) {
495 std::vector<mp_word_t> ws;
496 return this->mul(y, ws);
502 const size_t y_sw = y.sig_words();
505 z.resize(
size() + y.size());
507 if(x_sw == 1 && y_sw) {
509 }
else if(y_sw == 1 && x_sw) {
511 }
else if(x_sw && y_sw) {
514 z.cond_flip_sign(x_sw > 0 && y_sw > 0 &&
sign() != y.sign());
520 (*this) >>= (y.
bits() - 1);
522 (*this) = (*this) / y;
532 vartime_divide(*
this, y, q, r);
540 return (*
this = (*
this) % mod);
557 vartime_divide(*
this, mod, q, r);
683 mp_word_t conversion_radix, radix_digits;
685 conversion_radix = 10000000000000000000U;
688 conversion_radix = 1000000000U;
693 const size_t digit_estimate =
static_cast<size_t>(1 + (this->
bits() / 3.32));
696 const size_t digit_blocks = (digit_estimate + radix_digits - 1) / radix_digits;
702 std::vector<mp_word_t> digit_groups(digit_blocks);
704 for(
size_t i = 0; i != digit_blocks; ++i) {
706 ct_divide_word(value, conversion_radix, value, remainder);
707 digit_groups[i] = remainder;
712 std::vector<uint8_t> digits(digit_blocks * radix_digits);
714 for(
size_t i = 0; i != digit_blocks; ++i) {
716 for(
size_t j = 0; j != radix_digits; ++j)
721 digits[radix_digits*i + j] =
static_cast<uint8_t
>(digit);
726 while(!digits.empty() && digits.back() == 0) {
730 assert(digit_estimate >= digits.size());
734 s.reserve(1 + digits.size());
741 for(
auto i = digits.rbegin(); i != digits.rend(); ++i) {
742 s.push_back(*i +
'0');
755 std::vector<uint8_t>
bits;
762 data_len =
bits.size();
764 data =
reinterpret_cast<const uint8_t*
>(m_data.const_data());
785 : m_reg(), m_sig_words(sig_words_npos) {}
787 data_t(
const data_t& o)
noexcept =
default;
789 data_t(data_t&& o)
noexcept {
792 data_t(std::vector<mp_word_t>&& reg)
noexcept {
796 ~data_t() noexcept = default;
798 data_t& operator=(const data_t& r) noexcept = default;
800 data_t& operator=(data_t&& other) noexcept {
806 data_t&
operator=(std::vector<mp_word_t>&& other_reg)
noexcept {
807 if(&m_reg != &other_reg) {
808 this->
swap(other_reg);
814 invalidate_sig_words();
818 const mp_word_t* const_data() const noexcept {
822 std::vector<mp_word_t>& mutable_vector() noexcept {
823 invalidate_sig_words();
827 const std::vector<mp_word_t>& const_vector() const noexcept {
831 mp_word_t get_word_at(
size_t n)
const noexcept {
832 if(n < m_reg.size()) {
838 void set_word_at(
size_t i,
mp_word_t w) {
839 invalidate_sig_words();
840 if(i >= m_reg.size()) {
849 void set_words(
const mp_word_t w[],
size_t len) {
850 invalidate_sig_words();
851 m_reg.assign(w, w + len);
855 m_reg.resize(m_reg.capacity());
856 clear_mem(m_reg.data(), m_reg.size());
860 void set_size(
size_t s) {
861 invalidate_sig_words();
862 clear_mem(m_reg.data(), m_reg.size());
863 m_reg.resize(s + (8 - (s % 8)));
866 void mask_bits(
size_t n)
noexcept {
867 if(n == 0) {
return set_to_zero(); }
872 if(top_word <
size())
875 const size_t len =
size() - (top_word + 1);
878 clear_mem(&m_reg[top_word+1], len);
880 m_reg[top_word] &= mask;
881 invalidate_sig_words();
885 void grow_to(
size_t n)
const {
887 if(n <= m_reg.capacity()) {
890 m_reg.resize(n + (8 - (n % 8)));
895 size_t size() const noexcept {
return m_reg.size(); }
897 void shrink_to_fit(
size_t min_size = 0) {
902 void resize(
size_t s) {
906 void swap(data_t& other)
noexcept {
907 m_reg.swap(other.m_reg);
908 std::swap(m_sig_words, other.m_sig_words);
911 void swap(std::vector<mp_word_t>& reg)
noexcept {
913 invalidate_sig_words();
916 void invalidate_sig_words() const noexcept {
917 m_sig_words = sig_words_npos;
921 if(m_sig_words == sig_words_npos) {
922 m_sig_words = calc_sig_words();
924 assert(m_sig_words == calc_sig_words());
929 static const size_t sig_words_npos =
static_cast<size_t>(-1);
931 size_t calc_sig_words() const noexcept {
932 const size_t sz = m_reg.size();
937 for(
size_t i = 0; i != sz; ++i)
953 mutable std::vector<mp_word_t> m_reg;
954 mutable size_t m_sig_words = sig_words_npos;
965 template<
typename T>
static inline constexpr uint8_t get_byte_var_be(
size_t byte_num, T input)
noexcept {
966 return static_cast<uint8_t
>( input >> (((~byte_num)&(
sizeof(T)-1)) << 3) );
974 template<
typename T>
static inline constexpr uint8_t get_byte_var_le(
size_t byte_num, T input)
noexcept {
975 return static_cast<uint8_t
>( input >> ( byte_num << 3 ) );
986 static inline constexpr void clear_bytes(
void* ptr,
size_t bytes)
noexcept {
988 std::memset(ptr, 0,
bytes);
1002 template<
typename T>
static inline constexpr void clear_mem(T* ptr,
size_t n)
noexcept {
1003 clear_bytes(ptr,
sizeof(T)*n);
1010 void grow_to(
size_t n)
const { m_data.grow_to(n); }
1012 void resize(
size_t s) { m_data.resize(s); }
1014 void set_word_at(
size_t i,
mp_word_t w) {
1015 m_data.set_word_at(i, w);
1018 void set_words(
const mp_word_t w[],
size_t len) {
1019 m_data.set_words(w, len);
1025 mp_word_t* mutable_data() {
return m_data.mutable_data(); }
1033 void binary_decode(
const uint8_t buf[],
size_t byte_len,
const lb_endian_t byte_order) {
1034 const size_t full_words = byte_len /
sizeof(
mp_word_t);
1035 const size_t extra_bytes = byte_len %
sizeof(
mp_word_t);
1039 m_data.set_size(
jau::round_up(full_words + (extra_bytes > 0 ? 1U : 0U), 8U) );
1041 mp_word_t* sink = m_data.mutable_data();
1044 for(
size_t i = 0; i < full_words; ++i) {
1045 sink[i] = jau::get_value<mp_word_t>(buf +
sizeof(
mp_word_t)*i, byte_order);
1049 for(
size_t i = 0; i < full_words; ++i) {
1050 sink[i] = jau::get_value<mp_word_t>(buf + byte_len -
sizeof(
mp_word_t)*(i+1), byte_order);
1055 for(
size_t i = 0; i < extra_bytes; ++i) {
1059 for(
size_t i = 0; i < extra_bytes; ++i) {
1060 le_w = (le_w << 8) |
mp_word_t( buf[i] );
1072 static BigInt hex_decode(
const uint8_t buf[],
size_t str_len,
const lb_endian_t byte_order) {
1075 std::vector<uint8_t> bin_out;
1076 const size_t exp_blen = str_len / 2 + str_len % 2;
1078 if( exp_blen != blen ) {
1086 static BigInt dec_decode(
const uint8_t buf[],
size_t str_len) {
1090 for(
size_t i = 0; i < str_len; ++i) {
1091 const char c = buf[i];
1093 if(c < '0' || c >
'9') {
1096 const uint8_t x = c -
'0';
1120 const size_t full_words = byte_len /
sizeof(
mp_word_t);
1121 const size_t extra_bytes = byte_len %
sizeof(
mp_word_t);
1125 for(
size_t i = 0; i < full_words; ++i) {
1126 jau::put_value<mp_word_t>(output + i*
sizeof(
mp_word_t),
word_at(i), byte_order);
1130 for(
size_t i = 0; i < full_words; ++i) {
1131 jau::put_value<mp_word_t>(output + byte_len - (i+1)*
sizeof(
mp_word_t),
word_at(i), byte_order);
1134 if(extra_bytes > 0) {
1137 for(
size_t i = 0; i < extra_bytes; ++i) {
1138 output[full_words*
sizeof(
mp_word_t) + i] = get_byte_var_le(i, le_w);
1141 for(
size_t i = 0; i < extra_bytes; ++i) {
1142 output[extra_bytes-1-i] = get_byte_var_le(i, le_w);
1146 return extra_bytes + full_words *
sizeof(
mp_word_t);
1150 size_t top_bits_free() const noexcept {
1166 int cmp(
const BigInt& other,
bool check_signs =
true) const noexcept {
1168 if(other.is_positive() && this->is_negative()) {
1171 if(other.is_negative() && this->is_positive()) {
1174 if(other.is_negative() && this->is_negative()) {
1176 other.data(), other.size()));
1180 other.data(), other.size());
1183 bool is_equal(
const BigInt& other)
const noexcept {
1184 if(this->
sign() != other.sign()) {
1188 other.data(), other.sig_words()).is_set();
1191 bool is_less_than(
const BigInt& other)
const noexcept {
1198 if(other.is_negative() && this->is_negative()) {
1200 this->data(), this->sig_words()).is_set();
1203 other.data(), other.sig_words()).is_set();
1208 grow_to(
std::max(x_sw, y_words) + 1);
1210 if(
sign() == y_sign)
1216 if(relative_size >= 0)
1225 if(relative_size < 0) {
1227 }
else if(relative_size == 0) {
1235 return add(&y, 1, sign_t::positive);
1238 return add(&y, 1, sign_t::negative);
1242 const size_t x_sw = x.sig_words();
1246 if(x.sign() == y_sign) {
1248 z.set_sign(x.sign());
1250 const int32_t relative_size =
ops::bigint_sub_abs(z.mutable_data(), x.data(), x_sw, y, y_words);
1253 if(relative_size < 0) {
1255 }
else if(relative_size == 0) {
1258 z.set_sign(x.sign());
1264 BigInt& mul(
const BigInt& y, std::vector<mp_word_t>& ws)
noexcept {
1266 const size_t y_sw = y.sig_words();
1269 if(x_sw == 0 || y_sw == 0)
1274 else if(x_sw == 1 && y_sw)
1279 else if(y_sw == 1 && x_sw)
1282 set_word_at(x_sw, carry);
1286 const size_t new_size = x_sw + y_sw + 1;
1289 std::vector<mp_word_t> z_reg(new_size);
1293 this->swap_reg(z_reg);
1310 void cond_flip_sign(
bool predicate)
noexcept {
1313 const uint8_t current_sign =
static_cast<uint8_t
>(
sign());
1314 const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
1325 inline size_t reduce_below(
const BigInt& p, std::vector<mp_word_t>& ws) {
1326 if(p.is_negative() || this->is_negative()) {
1328 if( p.is_negative() ) {
1329 msg.append(
"p < 0");
1332 if( msg.length() > 0 ) {
1333 msg.append(
" and ");
1335 msg.append(
"*this < 0");
1339 const size_t p_words = p.sig_words();
1341 if(
size() < p_words + 1) {
1342 grow_to(p_words + 1);
1344 if(ws.size() < p_words + 1) {
1345 ws.resize(p_words + 1);
1347 clear_mem(ws.data(), ws.size());
1349 size_t reductions = 0;
1364 q.cond_flip_sign(x.sign() != y.sign());
1366 if(x.is_negative() && r.is_nonzero())
1396 if( y_arg.is_zero() ) {
1399 const size_t y_words = y_arg.sig_words();
1401 assert(y_words > 0);
1407 std::vector<mp_word_t> ws;
1413 const size_t shifts = y.top_bits_free();
1419 const size_t t = y_words - 1;
1420 const size_t n =
std::max(y_words, r.sig_words()) - 1;
1423 q.grow_to(n - t + 1);
1430 q_words[n-t] = r.reduce_below(shifted_y, ws);
1436 for(
size_t j = n; j != t; --j) {
1446 qjt -= division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2);
1447 qjt -= division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2);
1448 assert(division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2) ==
false);
1454 r -= shifted_y * qjt;
1455 qjt -= r.is_negative();
1456 r += shifted_y *
static_cast<mp_word_t>(r.is_negative());
1458 q_words[j-t-1] = qjt;
1463 sign_fixup(x, y_arg, q, r);
1475 ct_divide_word(*
this, y, q, r);
1483 const size_t x_words = x.sig_words();
1484 const size_t x_bits = x.bits();
1489 for(
size_t i = 0; i != x_bits; ++i)
1491 const size_t b = x_bits - 1 - i;
1492 const bool x_b = x.get_bit(b);
1500 q.conditionally_set_bit(b, r_gte_y.is_set());
1501 r = r_gte_y.select(r - y, r);
1504 if(x.is_negative()) {
1526 remainder = (
word_at(0) & (mod - 1));
1529 for(
size_t i = sw; i > 0; --i) {
1534 return mod - remainder;
1539 void append_detail(std::string& s)
const noexcept {
1563 return x < y ? x : y;
1566 return x > y ? x : y;
1569 return min(
max(x, min_val), max_val);
1573 return x < y ? x : y;
1576 return x > y ? x : y;
1579 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.
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
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...
std::string to_dec_string(bool add_details=false) const noexcept
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
! operator, returns true iff this is zero, otherwise false.
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 mod_pow(BigInt e, BigInt m)
Returns (*this)^e % m, or pow(*this, e) % m.
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 & 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.
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 bool is_little_endian(const endian_t byte_order) noexcept
Returns true if given byte_order equals endian::little, otherwise false.
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.
std::string to_string(const alphabet &v) noexcept
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).
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), actually O(n/2).
constexpr T min(const T x, const T y) noexcept
Returns the minimum of two integrals (w/ branching) in O(1)
mp::BigInt & max(mp::BigInt &x, mp::BigInt &y) noexcept
constexpr T gcd(T a, T b) noexcept
Returns the greatest common divisor (GCD) of the two given integer values following Euclid's algorith...
constexpr T max(const T x, const T y) noexcept
Returns the maximum of two integrals (w/ branching) in O(1)
mp::BigInt pow(mp::BigInt b, mp::BigInt e)
constexpr T abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/ branching) in O(1)
constexpr bool is_power_of_2(const T x) noexcept
Power of 2 test (w/o branching ?) in O(1)
std::string bytesHexString(const void *data, const nsize_t offset, const nsize_t length, const bool lsbFirst, const bool lowerCase=true) noexcept
Produce a hexadecimal string representation of the given byte values.
size_t hexStringBytes(std::vector< uint8_t > &out, const std::string &hexstr, const bool lsbFirst, const bool checkLeading0x) noexcept
Converts a given hexadecimal string representation into a byte vector.
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.