12template <
class base_u
int>
21 return { *
this,
uintx(0) };
27 return {
uintx(0), *
this };
31 uintx remainder = *
this;
33 uint64_t bit_difference =
get_msb() -
b.get_msb();
35 uintx divisor =
b << bit_difference;
36 uintx accumulator =
uintx(1) << bit_difference;
39 if (divisor > remainder) {
46 while (remainder >=
b) {
50 if (remainder >= divisor) {
54 quotient |= accumulator;
78 uintx r2 = (*
this > modulus) ? *
this % modulus : *
this;
86 t2 = temp_t1 - q * t2;
88 r2 = temp_r1 - q * r2;
109 if (modulus.
get_msb() >= (2 * base_uint::length() - 1)) {
114 return this->unsafe_invmod(modulus);
119 if (bit_index >= base_uint::length()) {
120 return hi.get_bit(bit_index - base_uint::length());
122 return lo.get_bit(bit_index);
127 return uintx(0) - *
this;
133 const auto lohi = lo.mul_extended(other.
hi);
134 const auto hilo = hi.mul_extended(other.
lo);
136 base_uint top = lolo.second + hilo.first + lohi.first;
137 base_uint bottom = lolo.first;
138 return { bottom, top };
141template <
class base_u
int>
145 const auto lohi = lo.mul_extended(other.
hi);
146 const auto hilo = hi.mul_extended(other.
lo);
147 const auto hihi = hi.mul_extended(other.
hi);
149 base_uint t0 = lolo.first;
150 base_uint t1 = lolo.second;
151 base_uint t2 = hilo.second;
152 base_uint t3 = hihi.second;
153 base_uint t2_carry(0);
154 base_uint t3_carry(0);
156 t2_carry += (t1 < hilo.first ? base_uint(1) : base_uint(0));
158 t2_carry += (t1 < lohi.first ? base_uint(1) : base_uint(0));
160 t3_carry += (t2 < lohi.second ? base_uint(1) : base_uint(0));
162 t3_carry += (t2 < hihi.first ? base_uint(1) : base_uint(0));
164 t3_carry += (t2 < t2_carry ? base_uint(1) : base_uint(0));
172 return divmod(other).first;
178 return divmod(other).second;
183 return { lo ^ other.
lo, hi ^ other.
hi };
188 return { lo | other.
lo, hi | other.
hi };
198 return ((lo == other.
lo) && (hi == other.
hi));
203 return !(*
this == other);
208 return *
this ==
uintx(0ULL);
213 bool hi_gt = hi > other.
hi;
214 bool lo_gt = lo > other.
lo;
216 bool gt = (hi_gt) || (lo_gt && (hi == other.
hi));
222 return (*
this > other) || (*
this == other);
227 return other > *
this;
232 return (*
this < other) || (*
this == other);
239 uint256_t(0x3C208C16D87CFD47UL, 0x97816a916871ca8dUL, 0xb85045b68181585dUL, 0x30644e72e131a029UL);
240 constexpr uint256_t SECP256K1FQMODULUS256 =
241 uint256_t(0xFFFFFFFEFFFFFC2FULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL);
242 constexpr uint256_t SECP256R1FQMODULUS256 =
243 uint256_t(0xFFFFFFFFFFFFFFFFULL, 0x00000000FFFFFFFFULL, 0x0000000000000000ULL, 0xFFFFFFFF00000001ULL);
245 if (
b ==
uintx(BN254FQMODULUS256)) {
246 return (*this).template barrett_reduction<BN254FQMODULUS256>();
248 if (
b ==
uintx(SECP256K1FQMODULUS256)) {
249 return (*this).template barrett_reduction<SECP256K1FQMODULUS256>();
251 if (
b ==
uintx(SECP256R1FQMODULUS256)) {
252 return (*this).template barrett_reduction<SECP256R1FQMODULUS256>();
255 return divmod_base(
b);
269template <
class base_u
int>
270template <base_u
int modulus>
275 constexpr size_t k = base_uint::length() - 1;
278 static const uintx redc_parameter = ((
uintx(1) << (k * 2)).divmod_base(
uintx(modulus))).first;
280 const auto x = *
this;
284 constexpr size_t shift = 2 * k;
289 const uintx downshifted_hi_bits = mul_result.second & ((
uintx(1) << shift) - 1);
290 const uintx mul_hi_underflow =
uintx(downshifted_hi_bits) << (length() - shift);
291 uintx quotient = (mul_result.first >> shift) | mul_hi_underflow;
296 const auto lolo = quotient.
lo.mul_extended(modulus);
297 const auto lohi = quotient.
hi.mul_extended(modulus);
298 base_uint t0 = lolo.first;
299 base_uint t1 = lolo.second;
300 t1 = t1 + lohi.first;
301 qm_lo =
uintx(t0, t1);
303 uintx remainder = x - qm_lo;
309 while (remainder >=
uintx(modulus)) {
311 remainder = remainder - modulus;
312 quotient = quotient + 1;
#define BB_ASSERT(expression,...)
#define BB_ASSERT_LT(left, right,...)
uintx operator%(const uintx &other) const
std::pair< uintx, uintx > divmod(const uintx &b) const
bool operator!=(const uintx &other) const
bool operator<(const uintx &other) const
uintx operator*(const uintx &other) const
uintx unsafe_invmod(const uintx &modulus) const
std::pair< uintx, uintx > divmod_base(const uintx &b) const
bool operator==(const uintx &other) const
bool operator>(const uintx &other) const
bool operator<=(const uintx &other) const
bool get_bit(uint64_t bit_index) const
constexpr uint64_t get_msb() const
std::pair< uintx, uintx > barrett_reduction() const
uintx operator|(const uintx &other) const
bool operator>=(const uintx &other) const
uintx operator/(const uintx &other) const
std::pair< uintx, uintx > mul_extended(const uintx &other) const
uintx invmod(const uintx &modulus) const
uintx operator^(const uintx &other) const
constexpr T get_msb(const T in)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept