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;
77 uintx r2 = (*
this > modulus) ? *
this % modulus : *
this;
85 t2 = temp_t1 - q * t2;
87 r2 = temp_r1 - q * r2;
110 if (modulus.
get_msb() >= (2 * base_uint::length() - 1)) {
115 return this->unsafe_invmod(modulus);
120 if (bit_index >= base_uint::length()) {
121 return hi.get_bit(bit_index - base_uint::length());
123 return lo.get_bit(bit_index);
128 return uintx(0) - *
this;
134 const auto lohi = lo.mul_extended(other.
hi);
135 const auto hilo = hi.mul_extended(other.
lo);
137 base_uint top = lolo.second + hilo.first + lohi.first;
138 base_uint bottom = lolo.first;
139 return { bottom, top };
142template <
class base_u
int>
146 const auto lohi = lo.mul_extended(other.
hi);
147 const auto hilo = hi.mul_extended(other.
lo);
148 const auto hihi = hi.mul_extended(other.
hi);
150 base_uint t0 = lolo.first;
151 base_uint t1 = lolo.second;
152 base_uint t2 = hilo.second;
153 base_uint t3 = hihi.second;
154 base_uint t2_carry(0);
155 base_uint t3_carry(0);
157 t2_carry += (t1 < hilo.first ? base_uint(1) : base_uint(0));
159 t2_carry += (t1 < lohi.first ? base_uint(1) : base_uint(0));
161 t3_carry += (t2 < lohi.second ? base_uint(1) : base_uint(0));
163 t3_carry += (t2 < hihi.first ? base_uint(1) : base_uint(0));
165 t3_carry += (t2 < t2_carry ? base_uint(1) : base_uint(0));
173 return divmod(other).first;
179 return divmod(other).second;
184 return { lo ^ other.
lo, hi ^ other.
hi };
189 return { lo | other.
lo, hi | other.
hi };
199 return ((lo == other.
lo) && (hi == other.
hi));
204 return !(*
this == other);
209 return *
this ==
uintx(0ULL);
214 bool hi_gt = hi > other.
hi;
215 bool lo_gt = lo > other.
lo;
217 bool gt = (hi_gt) || (lo_gt && (hi == other.
hi));
223 return (*
this > other) || (*
this == other);
228 return other > *
this;
233 return (*
this < other) || (*
this == other);
240 uint256_t(0x3C208C16D87CFD47UL, 0x97816a916871ca8dUL, 0xb85045b68181585dUL, 0x30644e72e131a029UL);
241 constexpr uint256_t SECP256K1FQMODULUS256 =
242 uint256_t(0xFFFFFFFEFFFFFC2FULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL);
243 constexpr uint256_t SECP256R1FQMODULUS256 =
244 uint256_t(0xFFFFFFFFFFFFFFFFULL, 0x00000000FFFFFFFFULL, 0x0000000000000000ULL, 0xFFFFFFFF00000001ULL);
246 if (
b ==
uintx(BN254FQMODULUS256)) {
247 return (*this).template barrett_reduction<BN254FQMODULUS256>();
249 if (
b ==
uintx(SECP256K1FQMODULUS256)) {
250 return (*this).template barrett_reduction<SECP256K1FQMODULUS256>();
252 if (
b ==
uintx(SECP256R1FQMODULUS256)) {
253 return (*this).template barrett_reduction<SECP256R1FQMODULUS256>();
256 return divmod_base(
b);
270template <
class base_u
int>
271template <base_u
int modulus>
276 constexpr size_t k = base_uint::length() - 1;
279 static const uintx redc_parameter = ((
uintx(1) << (k * 2)).divmod_base(
uintx(modulus))).first;
281 const auto x = *
this;
285 constexpr size_t shift = 2 * k;
290 const uintx downshifted_hi_bits = mul_result.second & ((
uintx(1) << shift) - 1);
291 const uintx mul_hi_underflow =
uintx(downshifted_hi_bits) << (
length() - shift);
292 uintx quotient = (mul_result.first >> shift) | mul_hi_underflow;
297 const auto lolo = quotient.
lo.mul_extended(modulus);
298 const auto lohi = quotient.
hi.mul_extended(modulus);
299 base_uint t0 = lolo.first;
300 base_uint t1 = lolo.second;
301 t1 = t1 + lohi.first;
302 qm_lo =
uintx(t0, t1);
304 uintx remainder = x - qm_lo;
310 while (remainder >=
uintx(modulus)) {
312 remainder = remainder - modulus;
313 quotient = quotient + 1;
#define BB_ASSERT_LT(left, right,...)
#define ASSERT(expression,...)
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
uint8_t const size_t length
constexpr T get_msb(const T in)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept