36 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
37 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
39 return montgomery_mul(other);
42 return montgomery_mul(other);
44 field result = asm_mul_with_coarse_reduction(*
this, other);
52 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
53 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
60 asm_self_mul_with_coarse_reduction(*
this, other);
74 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
75 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
76 return montgomery_square();
79 return montgomery_square();
81 field result = asm_sqr_with_coarse_reduction(*
this);
89 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
90 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
91 *
this = montgomery_square();
94 *
this = montgomery_square();
96 asm_self_sqr_with_coarse_reduction(*
this);
109 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
110 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
116 field result = asm_add_with_coarse_reduction(*
this, other);
124 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
125 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
131 asm_self_add_with_coarse_reduction(*
this, other);
132 assert_coarse_form();
146 field<T> value_before_incrementing = *
this;
148 return value_before_incrementing;
158 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
159 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
160 return subtract(other);
163 return subtract(other);
165 field result = asm_sub_with_coarse_reduction(*
this, other);
177 constexpr field p{ modulus.
data[0], modulus.data[1], modulus.data[2], modulus.data[3] };
183 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
184 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
185 *
this = subtract(other);
188 *
this = subtract(other);
190 asm_self_sub_with_coarse_reduction(*
this, other);
191 assert_coarse_form();
200 constexpr field p{ modulus.
data[0], modulus.data[1], modulus.data[2], modulus.data[3] };
206 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
207 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
208 *
this = predicate ? -(*this) : *
this;
211 *
this = predicate ? -(*this) : *
this;
213 asm_conditional_negate(*
this, predicate);
231 const field left = reduce_once();
233 const bool t0 = left.
data[3] > right.
data[3];
234 const bool t1 = (left.
data[3] == right.
data[3]) && (left.
data[2] > right.
data[2]);
237 const bool t3 = (left.
data[3] == right.
data[3]) && (left.
data[2] == right.
data[2]) &&
239 return (t0 || t1 || t2 || t3);
255 return (other > *
this);
263 const field left = reduce_once();
271 return (!
operator==(other));
287 constexpr field r_squared =
288 field{ r_squared_uint.
data[0], r_squared_uint.data[1], r_squared_uint.data[2], r_squared_uint.data[3] };
289 return *
this * r_squared;
294 constexpr field one_raw{ 1, 0, 0, 0 };
300 constexpr field r_squared =
301 field{ r_squared_uint.
data[0], r_squared_uint.data[1], r_squared_uint.data[2], r_squared_uint.data[3] };
307 constexpr field one_raw{ 1, 0, 0, 0 };
324 self_to_montgomery_form();
330 self_from_montgomery_form();
336 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
337 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
343 return asm_reduce_once(*
this);
349 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
350 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
356 asm_self_reduce_once(*
this);
365 const uint64_t maximum_set_bit = exponent.get_msb();
367 for (
int i =
static_cast<int>(maximum_set_bit) - 1; i >= 0; --i) {
369 if (exponent.get_bit(
static_cast<uint64_t
>(i))) {
370 accumulator *= to_mul;
375 }
else if (*
this == zero()) {
376 accumulator = zero();
383 return pow({ exponent, 0, 0, 0 });
388 if (*
this == zero()) {
391 return pow(modulus_minus_two);
396 batch_invert(std::span{ coeffs, n });
401 batch_invert<decltype(coeffs)>(coeffs);
414 requires requires(
C& c) {
420 const size_t n = coeffs.size();
423 std::vector<bool> skipped;
424 temporaries.resize(n);
427 field accumulator = one();
428 for (
size_t i = 0; i < n; ++i) {
429 temporaries[i] = accumulator;
430 if (coeffs[i].is_zero()) {
434 accumulator *= coeffs[i];
437 accumulator = accumulator.
invert();
440 for (
size_t i = n - 1; i < n; --i) {
442 T0 = accumulator * temporaries[i];
443 accumulator *= coeffs[i];
485 constexpr uint256_t Q = (modulus - 1) >>
static_cast<uint64_t
>(primitive_root_log_size());
486 constexpr uint256_t Q_minus_one_over_two = (Q - 1) >> 1;
488 field v = pow(Q_minus_one_over_two);
501 for (
size_t i = 0; i < primitive_root_log_size() - 1; ++i) {
514 constexpr field g = coset_generator().pow(Q);
517 constexpr field g_inv = coset_generator().
pow(modulus - 1 - Q);
520 constexpr size_t root_bits = primitive_root_log_size();
525 constexpr size_t table_bits = 6;
529 constexpr size_t num_tables = root_bits / table_bits + (root_bits % table_bits != 0 ? 1 : 0);
530 constexpr size_t num_offset_tables = num_tables - 1;
533 constexpr size_t table_size =
static_cast<size_t>(1UL) << table_bits;
539 constexpr auto get_g_table = [&](
const field& h) {
542 for (
size_t i = 1; i < table_size; ++i) {
543 result[i] = result[i - 1] * h;
552 field working_base = g_inv;
554 for (
size_t i = 0; i < num_tables; ++i) {
555 result[i] = get_g_table(working_base);
557 for (
size_t j = 0; j < table_bits; ++j) {
568 field working_base = g_inv;
570 for (
size_t i = 0; i < root_bits % table_bits; ++i) {
574 for (
size_t i = 0; i < num_offset_tables; ++i) {
575 result[i] = get_g_table(working_base);
576 for (
size_t j = 0; j < table_bits; ++j) {
577 working_base.self_sqr();
586 constexpr GTable root_table_a = get_g_table(
g.pow(1UL << ((num_tables - 1) * table_bits)));
588 constexpr GTable root_table_b = get_g_table(
g.pow(1UL << (root_bits - table_bits)));
597 for (
size_t i = 0; i < num_tables - 1; ++i) {
598 uvv_powers[i] = base;
599 for (
size_t j = 0; j < table_bits; ++j) {
603 uvv_powers[num_tables - 1] = base;
611 for (
size_t i = 0; i < num_tables; ++i) {
613 size_t table_index = num_tables - 1 - i;
616 field target = uvv_powers[table_index];
620 for (
size_t j = 0; j < i; ++j) {
621 size_t e_idx = num_tables - 1 - (i - 1) + j;
622 size_t g_idx = num_tables - 2 - j;
626 g_lookup = offset_g_tables[g_idx - 1][e_slices[e_idx]];
628 g_lookup = g_tables[g_idx][e_slices[e_idx]];
639 for (
auto& x : root_table_a) {
647 for (
auto& x : root_table_b) {
655 if (count == table_size) {
659 e_slices[table_index] = count;
669 for (
size_t i = 0; i < num_tables; ++i) {
670 auto& e_slice = e_slices[num_tables - 1 - i];
674 if ((e_slice & 1UL) == 1UL) {
677 size_t borrow_value = (i == 1) ? 1UL << ((root_bits % table_bits) - 1) : (1UL << (table_bits - 1));
678 e_slices[num_tables - i] += borrow_value;
688 field g_pow_minus_e_over_2 = 1;
689 for (
size_t i = 0; i < num_tables; ++i) {
691 g_pow_minus_e_over_2 *= g_tables[i][e_slices[num_tables - 1 - i]];
693 g_pow_minus_e_over_2 *= offset_g_tables[i - 1][e_slices[num_tables - 1 - i]];
697 auto result = uv * g_pow_minus_e_over_2;
698 if (result * result != *
this) {
706 requires((T::modulus_0 & 0x3UL) == 0x3UL)
709 field root = pow(sqrt_exponent);
710 if ((root * root) == (*
this)) {
718 requires((T::modulus_0 & 0x3UL) != 0x3UL)
720 field root = tonelli_shanks_sqrt();
721 if ((root * root) == (*
this)) {
734 *
this = operator/(other);
740 data[3] = 0ULL | (1ULL << 63ULL);
745 return (
data[3] >> 63ULL) == 1ULL;
750 return (
data[3] >> 63ULL);
759 const uint64_t mod_zero =
760 (
data[0] ^ T::modulus_0) | (
data[1] ^ T::modulus_1) | (
data[2] ^ T::modulus_2) | (
data[3] ^ T::modulus_3);
761 return static_cast<bool>(
static_cast<uint64_t
>(raw_zero == 0) |
static_cast<uint64_t
>(mod_zero == 0));
766#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
767 field r{ T::primitive_root_0, T::primitive_root_1, T::primitive_root_2, T::primitive_root_3 };
769 field r{ T::primitive_root_wasm_0, T::primitive_root_wasm_1, T::primitive_root_wasm_2, T::primitive_root_wasm_3 };
771 for (
size_t i = primitive_root_log_size(); i > subgroup_size; --i) {
787 return lo + (pow_2_256 * hi);
794 while (!target.
get_bit(result)) {
806 auto adjusted = from_montgomery_form_reduced();
811 uint64_t bin_data[4] = {
812 htonll(adjusted.data[3]), htonll(adjusted.data[2]), htonll(adjusted.data[1]), htonll(adjusted.data[0])
816 packer.pack_bin(
sizeof(bin_data));
817 packer.pack_bin_body((
const char*)bin_data,
sizeof(bin_data));
826 std::array<uint8_t,
sizeof(
data)> raw_data = o;
830 uint64_t* cast_data = (uint64_t*)&raw_data[0];
831 uint64_t reversed[] = { ntohll(cast_data[3]), ntohll(cast_data[2]), ntohll(cast_data[1]), ntohll(cast_data[0]) };
834 for (
int i = 0; i < 4; i++) {
835 data[i] = reversed[i];
840 throw_or_abort(
"msgpack field deserialization: non-canonical encoding (value >= modulus)");
844 *
this = to_montgomery_form();
virtual uint256_t get_random_uint256()=0
constexpr bool get_bit(uint64_t bit_index) const
const std::vector< MemoryValue > data
Entry point for Barretenberg command-line interface.
Univariate< Fr, domain_end > operator+(const Fr &ff, const Univariate< Fr, domain_end > &uv)
void assert_failure(std::string const &err)
Univariate< Fr, domain_end > operator*(const Fr &ff, const Univariate< Fr, domain_end > &uv)
constexpr void g(state_array &state, size_t a, size_t b, size_t c, size_t d, uint32_t x, uint32_t y)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
General class for prime fields see Prime field documentation["field documentation"] for general imple...
void assert_coarse_form() const noexcept
BB_INLINE constexpr field from_montgomery_form_reduced() const noexcept
static constexpr field get_root_of_unity(size_t subgroup_size) noexcept
BB_INLINE constexpr field & operator+=(const field &other) &noexcept
BB_INLINE constexpr void self_to_montgomery_form_reduced() &noexcept
static constexpr field one()
BB_INLINE constexpr void self_reduce_once() &noexcept
BB_INLINE constexpr bool operator!=(const field &other) const noexcept
BB_INLINE constexpr field operator*(const field &other) const noexcept
BB_INLINE constexpr field operator+(const field &other) const noexcept
constexpr field tonelli_shanks_sqrt() const noexcept
Implements an optimized variant of Tonelli-Shanks via lookup tables. Algorithm taken from https://cr....
BB_INLINE constexpr void self_from_montgomery_form_reduced() &noexcept
BB_INLINE constexpr field to_montgomery_form() const noexcept
BB_INLINE constexpr void self_conditional_negate(uint64_t predicate) &noexcept
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
BB_INLINE constexpr field operator++() noexcept
constexpr field operator/(const field &other) const noexcept
BB_INLINE constexpr void self_sqr() &noexcept
constexpr field invert() const noexcept
BB_INLINE constexpr void self_neg() &noexcept
BB_INLINE constexpr bool operator==(const field &other) const noexcept
BB_INLINE constexpr bool is_msb_set() const noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field sqr() const noexcept
BB_INLINE constexpr bool operator>(const field &other) const noexcept
Greater-than operator.
BB_INLINE constexpr field to_montgomery_form_reduced() const noexcept
BB_INLINE constexpr field & operator-=(const field &other) &noexcept
void msgpack_pack(auto &packer) const
constexpr std::pair< bool, field > sqrt() const noexcept
Compute square root of the field element.
BB_INLINE constexpr void self_from_montgomery_form() &noexcept
BB_INLINE constexpr field & operator*=(const field &other) &noexcept
BB_INLINE constexpr bool is_zero() const noexcept
static void batch_invert(C &coeffs) noexcept
Batch invert a collection of field elements using Montgomery's trick.
BB_INLINE constexpr void self_to_montgomery_form() &noexcept
BB_INLINE constexpr field from_montgomery_form() const noexcept
BB_INLINE constexpr field operator-() const noexcept
BB_INLINE constexpr bool operator<(const field &other) const noexcept
Less-than operator.
BB_INLINE constexpr void self_set_msb() &noexcept
void msgpack_unpack(auto o)
constexpr field & operator/=(const field &other) &noexcept
static constexpr size_t primitive_root_log_size() noexcept
BB_INLINE constexpr field reduce_once() const noexcept
static constexpr field zero()
BB_INLINE constexpr uint64_t is_msb_set_word() const noexcept
void throw_or_abort(std::string const &err)