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 return asm_mul_with_coarse_reduction(*
this, other);
50 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
51 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
58 asm_self_mul_with_coarse_reduction(*
this, other);
71 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
72 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
73 return montgomery_square();
76 return montgomery_square();
78 return asm_sqr_with_coarse_reduction(*
this);
84 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
85 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
86 *
this = montgomery_square();
89 *
this = montgomery_square();
91 asm_self_sqr_with_coarse_reduction(*
this);
103 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
104 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
110 return asm_add_with_coarse_reduction(*
this, other);
116 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
117 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
123 asm_self_add_with_coarse_reduction(*
this, other);
137 field<T> value_before_incrementing = *
this;
139 return value_before_incrementing;
149 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
150 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
151 return subtract(other);
154 return subtract(other);
156 return asm_sub_with_coarse_reduction(*
this, other);
162 if constexpr ((T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
163 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
164 constexpr field p{ modulus.
data[0], modulus.data[1], modulus.data[2], modulus.data[3] };
184 constexpr field p{ twice_modulus.
data[0], twice_modulus.data[1], twice_modulus.data[2], twice_modulus.data[3] };
185 return (p - *
this).reduce_once();
190 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
191 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
192 *
this = subtract(other);
195 *
this = subtract(other);
197 asm_self_sub_with_coarse_reduction(*
this, other);
205 if constexpr ((T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
206 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
207 constexpr field p{ modulus.
data[0], modulus.data[1], modulus.data[2], modulus.data[3] };
210 constexpr field p{ twice_modulus.
data[0], twice_modulus.data[1], twice_modulus.data[2], twice_modulus.data[3] };
211 *
this = (p - *
this).reduce_once();
217 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
218 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
219 *
this = predicate ? -(*this) : *
this;
222 *
this = predicate ? -(*this) : *
this;
224 asm_conditional_negate(*
this, predicate);
242 const field left = reduce_once();
244 const bool t0 = left.
data[3] > right.
data[3];
245 const bool t1 = (left.
data[3] == right.
data[3]) && (left.
data[2] > right.
data[2]);
248 const bool t3 = (left.
data[3] == right.
data[3]) && (left.
data[2] == right.
data[2]) &&
250 return (t0 || t1 || t2 || t3);
266 return (other > *
this);
274 const field left = reduce_once();
282 return (!
operator==(other));
298 constexpr field r_squared =
299 field{ r_squared_uint.
data[0], r_squared_uint.data[1], r_squared_uint.data[2], r_squared_uint.data[3] };
300 return *
this * r_squared;
305 constexpr field one_raw{ 1, 0, 0, 0 };
311 constexpr field r_squared =
312 field{ r_squared_uint.
data[0], r_squared_uint.data[1], r_squared_uint.data[2], r_squared_uint.data[3] };
318 constexpr field one_raw{ 1, 0, 0, 0 };
335 self_to_montgomery_form();
341 self_from_montgomery_form();
347 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
348 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
354 return asm_reduce_once(*
this);
360 if constexpr (
BBERG_NO_ASM || (T::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) ||
361 (T::modulus_1 == 0 && T::modulus_2 == 0 && T::modulus_3 == 0)) {
367 asm_self_reduce_once(*
this);
376 const uint64_t maximum_set_bit = exponent.get_msb();
378 for (
int i =
static_cast<int>(maximum_set_bit) - 1; i >= 0; --i) {
380 if (exponent.get_bit(
static_cast<uint64_t
>(i))) {
381 accumulator *= to_mul;
386 }
else if (*
this == zero()) {
387 accumulator = zero();
394 return pow({ exponent, 0, 0, 0 });
399 if (*
this == zero()) {
402 return pow(modulus_minus_two);
407 batch_invert(std::span{ coeffs, n });
412 batch_invert<decltype(coeffs)>(coeffs);
425 requires requires(
C& c) {
431 const size_t n = coeffs.size();
434 std::vector<bool> skipped;
435 temporaries.reserve(n);
438 field accumulator = one();
439 for (
size_t i = 0; i < n; ++i) {
440 temporaries[i] = accumulator;
441 if (coeffs[i].is_zero()) {
445 accumulator *= coeffs[i];
448 accumulator = accumulator.
invert();
451 for (
size_t i = n - 1; i < n; --i) {
453 T0 = accumulator * temporaries[i];
454 accumulator *= coeffs[i];
496 constexpr uint256_t Q = (modulus - 1) >>
static_cast<uint64_t
>(primitive_root_log_size());
497 constexpr uint256_t Q_minus_one_over_two = (Q - 1) >> 1;
499 field v = pow(Q_minus_one_over_two);
512 for (
size_t i = 0; i < primitive_root_log_size() - 1; ++i) {
525 constexpr field g = coset_generator().pow(Q);
528 constexpr field g_inv = coset_generator().
pow(modulus - 1 - Q);
531 constexpr size_t root_bits = primitive_root_log_size();
536 constexpr size_t table_bits = 6;
540 constexpr size_t num_tables = root_bits / table_bits + (root_bits % table_bits != 0 ? 1 : 0);
541 constexpr size_t num_offset_tables = num_tables - 1;
544 constexpr size_t table_size =
static_cast<size_t>(1UL) << table_bits;
550 constexpr auto get_g_table = [&](
const field& h) {
553 for (
size_t i = 1; i < table_size; ++i) {
554 result[i] = result[i - 1] * h;
563 field working_base = g_inv;
565 for (
size_t i = 0; i < num_tables; ++i) {
566 result[i] = get_g_table(working_base);
568 for (
size_t j = 0; j < table_bits; ++j) {
579 field working_base = g_inv;
581 for (
size_t i = 0; i < root_bits % table_bits; ++i) {
585 for (
size_t i = 0; i < num_offset_tables; ++i) {
586 result[i] = get_g_table(working_base);
587 for (
size_t j = 0; j < table_bits; ++j) {
588 working_base.self_sqr();
597 constexpr GTable root_table_a = get_g_table(
g.pow(1UL << ((num_tables - 1) * table_bits)));
599 constexpr GTable root_table_b = get_g_table(
g.pow(1UL << (root_bits - table_bits)));
608 for (
size_t i = 0; i < num_tables - 1; ++i) {
609 uvv_powers[i] = base;
610 for (
size_t j = 0; j < table_bits; ++j) {
614 uvv_powers[num_tables - 1] = base;
622 for (
size_t i = 0; i < num_tables; ++i) {
624 size_t table_index = num_tables - 1 - i;
627 field target = uvv_powers[table_index];
631 for (
size_t j = 0; j < i; ++j) {
632 size_t e_idx = num_tables - 1 - (i - 1) + j;
633 size_t g_idx = num_tables - 2 - j;
637 g_lookup = offset_g_tables[g_idx - 1][e_slices[e_idx]];
639 g_lookup = g_tables[g_idx][e_slices[e_idx]];
650 for (
auto& x : root_table_a) {
658 for (
auto& x : root_table_b) {
666 if (count == table_size) {
670 e_slices[table_index] = count;
680 for (
size_t i = 0; i < num_tables; ++i) {
681 auto& e_slice = e_slices[num_tables - 1 - i];
685 if ((e_slice & 1UL) == 1UL) {
688 size_t borrow_value = (i == 1) ? 1UL << ((root_bits % table_bits) - 1) : (1UL << (table_bits - 1));
689 e_slices[num_tables - i] += borrow_value;
699 field g_pow_minus_e_over_2 = 1;
700 for (
size_t i = 0; i < num_tables; ++i) {
702 g_pow_minus_e_over_2 *= g_tables[i][e_slices[num_tables - 1 - i]];
704 g_pow_minus_e_over_2 *= offset_g_tables[i - 1][e_slices[num_tables - 1 - i]];
708 auto result = uv * g_pow_minus_e_over_2;
709 if (result * result != *
this) {
717 requires((T::modulus_0 & 0x3UL) == 0x3UL)
720 field root = pow(sqrt_exponent);
721 if ((root * root) == (*
this)) {
729 requires((T::modulus_0 & 0x3UL) != 0x3UL)
731 field root = tonelli_shanks_sqrt();
732 if ((root * root) == (*
this)) {
745 *
this = operator/(other);
751 data[3] = 0ULL | (1ULL << 63ULL);
756 return (
data[3] >> 63ULL) == 1ULL;
761 return (
data[3] >> 63ULL);
767 (
data[0] == T::modulus_0 &&
data[1] == T::modulus_1 &&
data[2] == T::modulus_2 &&
data[3] == T::modulus_3);
772#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
773 field r{ T::primitive_root_0, T::primitive_root_1, T::primitive_root_2, T::primitive_root_3 };
775 field r{ T::primitive_root_wasm_0, T::primitive_root_wasm_1, T::primitive_root_wasm_2, T::primitive_root_wasm_3 };
777 for (
size_t i = primitive_root_log_size(); i > subgroup_size; --i) {
793 return lo + (pow_2_256 * hi);
800 while (!target.
get_bit(result)) {
812 auto adjusted = from_montgomery_form_reduced();
817 uint64_t bin_data[4] = {
818 htonll(adjusted.data[3]), htonll(adjusted.data[2]), htonll(adjusted.data[1]), htonll(adjusted.data[0])
822 packer.pack_bin(
sizeof(bin_data));
823 packer.pack_bin_body((
const char*)bin_data,
sizeof(bin_data));
832 std::array<uint8_t,
sizeof(
data)> raw_data = o;
836 uint64_t* cast_data = (uint64_t*)&raw_data[0];
837 uint64_t reversed[] = { ntohll(cast_data[3]), ntohll(cast_data[2]), ntohll(cast_data[1]), ntohll(cast_data[0]) };
840 for (
int i = 0; i < 4; i++) {
841 data[i] = reversed[i];
845 *
this = to_montgomery_form_reduced();
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...
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