48static constexpr uint64_t MODULUS_TOP_LIMB_LARGE_THRESHOLD = 0x4000000000000000ULL;
55template <
class Params_>
struct alignas(32)
field {
68#if defined(__wasm__) || !defined(__SIZEOF_INT128__)
69#define WASM_NUM_LIMBS 9
70#define WASM_LIMB_BITS 29
85 :
data{ input.
data[0], input.data[1], input.data[2], input.data[3] }
95 constexpr field(
const unsigned long input) noexcept
96 :
data{ input, 0, 0, 0 }
101 constexpr field(
const unsigned int input) noexcept
102 :
data{ input, 0, 0, 0 }
108 constexpr field(
const unsigned long long input) noexcept
109 :
data{ input, 0, 0, 0 }
114 constexpr field(
const int input) noexcept
118 data[0] =
static_cast<uint64_t
>(-input);
126 data[0] =
static_cast<uint64_t
>(input);
140 constexpr field(
const uint64_t
a,
const uint64_t
b,
const uint64_t c,
const uint64_t d) noexcept
159 constexpr explicit field(std::string input)
noexcept
170 constexpr explicit operator bool()
const
173 if (out.
data[0] != 0 && out.
data[0] != 1 && out.
data[1] != 0 && out.
data[2] != 0 && out.
data[3] != 0) {
176 return static_cast<bool>(out.
data[0]);
179 constexpr explicit operator uint8_t()
const
182 return static_cast<uint8_t
>(out.
data[0]);
185 constexpr explicit operator uint16_t()
const
188 return static_cast<uint16_t
>(out.
data[0]);
191 constexpr explicit operator uint32_t()
const
194 return static_cast<uint32_t
>(out.
data[0]);
197 constexpr explicit operator uint64_t()
const
208 return (hi << 64) | lo;
230 uint256_t{ Params::modulus_0, Params::modulus_1, Params::modulus_2, Params::modulus_3 };
231#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
233 Params_::r_squared_0, Params_::r_squared_1, Params_::r_squared_2, Params_::r_squared_3
237 Params_::r_squared_wasm_0, Params_::r_squared_wasm_1, Params_::r_squared_wasm_2, Params_::r_squared_wasm_3
239 static constexpr std::array<uint64_t, 9>
wasm_modulus = { Params::modulus_wasm_0, Params::modulus_wasm_1,
240 Params::modulus_wasm_2, Params::modulus_wasm_3,
241 Params::modulus_wasm_4, Params::modulus_wasm_5,
242 Params::modulus_wasm_6, Params::modulus_wasm_7,
243 Params::modulus_wasm_8 };
245 Params::r_inv_wasm_0, Params::r_inv_wasm_1, Params::r_inv_wasm_2, Params::r_inv_wasm_3, Params::r_inv_wasm_4,
246 Params::r_inv_wasm_5, Params::r_inv_wasm_6, Params::r_inv_wasm_7, Params::r_inv_wasm_8
253 if constexpr (Params::cube_root_0 != 0) {
254#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
255 constexpr field result{
256 Params::cube_root_0, Params::cube_root_1, Params::cube_root_2, Params::cube_root_3
259 constexpr field result{
260 Params::cube_root_wasm_0, Params::cube_root_wasm_1, Params::cube_root_wasm_2, Params::cube_root_wasm_3
267 constexpr field result = two_inv * numerator;
278#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
280 Params::coset_generators_0[7],
281 Params::coset_generators_1[7],
282 Params::coset_generators_2[7],
283 Params::coset_generators_3[7],
287 Params::coset_generators_wasm_0[7],
288 Params::coset_generators_wasm_1[7],
289 Params::coset_generators_wasm_2[7],
290 Params::coset_generators_wasm_3[7],
299#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
301 Params::coset_generators_0[6],
302 Params::coset_generators_1[6],
303 Params::coset_generators_2[6],
304 Params::coset_generators_3[6],
308 Params::coset_generators_wasm_0[6],
309 Params::coset_generators_wasm_1[6],
310 Params::coset_generators_wasm_2[6],
311 Params::coset_generators_wasm_3[6],
320 static_assert(idx < 7);
321#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
323 Params::coset_generators_0[idx],
324 Params::coset_generators_1[idx],
325 Params::coset_generators_2[idx],
326 Params::coset_generators_3[idx],
330 Params::coset_generators_wasm_0[idx],
331 Params::coset_generators_wasm_1[idx],
332 Params::coset_generators_wasm_2[idx],
333 Params::coset_generators_wasm_3[idx],
344 constexpr
field operator/(const
field& other) const noexcept;
355 constexpr
field& operator/=(const
field& other) & noexcept;
360 BB_INLINE constexpr
bool operator>(const
field& other) const noexcept;
361 BB_INLINE constexpr
bool operator<(const
field& other) const noexcept;
362 BB_INLINE constexpr
bool operator==(const
field& other) const noexcept;
363 BB_INLINE constexpr
bool operator!=(const
field& other) const noexcept;
381 template <typename
C>
383 requires requires(
C& c) {
396 requires((Params_::modulus_0 & 0x3UL) == 0x3UL);
398 requires((Params_::modulus_0 & 0x3UL) != 0x3UL);
436 if (predicate != 0) {
472 if constexpr (Params::modulus_3 >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) {
476 k1.
data[0] = ret.first[0];
477 k1.
data[1] = ret.first[1];
479#if !defined(__clang__) && defined(__GNUC__)
480#pragma GCC diagnostic push
481#pragma GCC diagnostic ignored "-Warray-bounds"
483 k2.
data[0] = ret.second[0];
484 k2.
data[1] = ret.second[1];
485#if !defined(__clang__) && defined(__GNUC__)
486#pragma GCC diagnostic pop
497 static_assert(Params::modulus_3 < MODULUS_TOP_LIMB_LARGE_THRESHOLD);
500 constexpr field endo_g1 = { Params::endo_g1_lo, Params::endo_g1_mid, Params::endo_g1_hi, 0 };
502 constexpr field endo_g2 = { Params::endo_g2_lo, Params::endo_g2_mid, 0, 0 };
504 constexpr field endo_minus_b1 = { Params::endo_minus_b1_lo, Params::endo_minus_b1_mid, 0, 0 };
506 constexpr field endo_b2 = { Params::endo_b2_lo, Params::endo_b2_mid, 0, 0 };
540 if (t1.
data[2] != 0 || t1.
data[3] != 0) {
554 constexpr field minus_b1f{
555 Params::endo_minus_b1_lo,
556 Params::endo_minus_b1_mid,
570 Params::endo_g1_hihi,
576 Params::endo_g2_hihi,
588 c1f.self_to_montgomery_form();
589 c2f.self_to_montgomery_form();
590 c1f = c1f * minus_b1f;
592 field r2f = c1f - c2f;
605 std::ios_base::fmtflags f(os.flags());
625 void msgpack_schema(auto& packer)
const { packer.pack_alias(Params::schema_name,
"bin32"); }
636 static_cast<uint8_t>(target.
data[0] & 15), static_cast<uint8_t>((target.
data[0] >> 4) & 15),
637 static_cast<uint8_t>((target.
data[0] >> 8) & 15), static_cast<uint8_t>((target.
data[0] >> 12) & 15),
638 static_cast<uint8_t>((target.
data[0] >> 16) & 15), static_cast<uint8_t>((target.
data[0] >> 20) & 15),
639 static_cast<uint8_t>((target.
data[0] >> 24) & 15), static_cast<uint8_t>((target.
data[0] >> 28) & 15),
640 static_cast<uint8_t>((target.
data[0] >> 32) & 15), static_cast<uint8_t>((target.
data[0] >> 36) & 15),
641 static_cast<uint8_t>((target.
data[0] >> 40) & 15), static_cast<uint8_t>((target.
data[0] >> 44) & 15),
642 static_cast<uint8_t>((target.
data[0] >> 48) & 15), static_cast<uint8_t>((target.
data[0] >> 52) & 15),
643 static_cast<uint8_t>((target.
data[0] >> 56) & 15), static_cast<uint8_t>((target.
data[0] >> 60) & 15),
644 static_cast<uint8_t>(target.
data[1] & 15), static_cast<uint8_t>((target.
data[1] >> 4) & 15),
645 static_cast<uint8_t>((target.
data[1] >> 8) & 15), static_cast<uint8_t>((target.
data[1] >> 12) & 15),
646 static_cast<uint8_t>((target.
data[1] >> 16) & 15), static_cast<uint8_t>((target.
data[1] >> 20) & 15),
647 static_cast<uint8_t>((target.
data[1] >> 24) & 15), static_cast<uint8_t>((target.
data[1] >> 28) & 15),
648 static_cast<uint8_t>((target.
data[1] >> 32) & 15), static_cast<uint8_t>((target.
data[1] >> 36) & 15),
649 static_cast<uint8_t>((target.
data[1] >> 40) & 15), static_cast<uint8_t>((target.
data[1] >> 44) & 15),
650 static_cast<uint8_t>((target.
data[1] >> 48) & 15), static_cast<uint8_t>((target.
data[1] >> 52) & 15),
651 static_cast<uint8_t>((target.
data[1] >> 56) & 15), static_cast<uint8_t>((target.
data[1] >> 60) & 15),
652 static_cast<uint8_t>(target.
data[2] & 15), static_cast<uint8_t>((target.
data[2] >> 4) & 15),
653 static_cast<uint8_t>((target.
data[2] >> 8) & 15), static_cast<uint8_t>((target.
data[2] >> 12) & 15),
654 static_cast<uint8_t>((target.
data[2] >> 16) & 15), static_cast<uint8_t>((target.
data[2] >> 20) & 15),
655 static_cast<uint8_t>((target.
data[2] >> 24) & 15), static_cast<uint8_t>((target.
data[2] >> 28) & 15),
656 static_cast<uint8_t>((target.
data[2] >> 32) & 15), static_cast<uint8_t>((target.
data[2] >> 36) & 15),
657 static_cast<uint8_t>((target.
data[2] >> 40) & 15), static_cast<uint8_t>((target.
data[2] >> 44) & 15),
658 static_cast<uint8_t>((target.
data[2] >> 48) & 15), static_cast<uint8_t>((target.
data[2] >> 52) & 15),
659 static_cast<uint8_t>((target.
data[2] >> 56) & 15), static_cast<uint8_t>((target.
data[2] >> 60) & 15),
660 static_cast<uint8_t>(target.
data[3] & 15), static_cast<uint8_t>((target.
data[3] >> 4) & 15),
661 static_cast<uint8_t>((target.
data[3] >> 8) & 15), static_cast<uint8_t>((target.
data[3] >> 12) & 15),
662 static_cast<uint8_t>((target.
data[3] >> 16) & 15), static_cast<uint8_t>((target.
data[3] >> 20) & 15),
663 static_cast<uint8_t>((target.
data[3] >> 24) & 15), static_cast<uint8_t>((target.
data[3] >> 28) & 15),
664 static_cast<uint8_t>((target.
data[3] >> 32) & 15), static_cast<uint8_t>((target.
data[3] >> 36) & 15),
665 static_cast<uint8_t>((target.
data[3] >> 40) & 15), static_cast<uint8_t>((target.
data[3] >> 44) & 15),
666 static_cast<uint8_t>((target.
data[3] >> 48) & 15), static_cast<uint8_t>((target.
data[3] >> 52) & 15),
667 static_cast<uint8_t>((target.
data[3] >> 56) & 15), static_cast<uint8_t>((target.
data[3] >> 60) & 15)
672#if defined(__wasm__) || !defined(__SIZEOF_INT128__)
708 uint64_t
a, uint64_t
b, uint64_t c, uint64_t carry_in, uint64_t& carry_out)
noexcept;
711 uint64_t
a, uint64_t
b, uint64_t c, uint64_t carry_in, uint64_t& out, uint64_t& carry_out)
noexcept;
713 BB_INLINE static constexpr uint64_t
mac_mini(uint64_t
a, uint64_t
b, uint64_t c, uint64_t& out)
noexcept;
716 uint64_t
a, uint64_t
b, uint64_t c, uint64_t& out, uint64_t& carry_out)
noexcept;
720 BB_INLINE static constexpr uint64_t
addc(uint64_t
a, uint64_t
b, uint64_t carry_in, uint64_t& carry_out)
noexcept;
722 BB_INLINE static constexpr uint64_t
sbb(uint64_t
a, uint64_t
b, uint64_t borrow_in, uint64_t& borrow_out)
noexcept;
727 uint64_t carry_in_lo,
728 uint64_t carry_in_hi,
730 uint64_t& carry_hi)
noexcept;
738#if (BBERG_NO_ASM == 0)
744 BB_INLINE static void asm_self_sqr_with_coarse_reduction(
const field&
a)
noexcept;
748 BB_INLINE static void asm_conditional_negate(
field& r, uint64_t predicate)
noexcept;
751 static constexpr uint64_t zero_reference = 0x00ULL;
757#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
758 static constexpr uint128_t lo_mask = 0xffffffffffffffffUL;
766 read(it, result.data[3]);
767 read(it, result.data[2]);
768 read(it, result.data[1]);
769 read(it, result.data[0]);
786template <
typename Params>
struct std::hash<
bb::field<Params>> {
790 auto reduced = ff.reduce_once();
group class. Represents an elliptic curve group element. Group is parametrised by Fq and Fr
std::unique_ptr< uint8_t[]> buffer
uintx< uint256_t > uint512_t
size_t hash_as_tuple(const Ts &... ts)
Entry point for Barretenberg command-line interface.
group< fq2, fr, Bn254G2Params > g2
group< fq, fr, Bn254G1Params > g1
void read(B &it, field2< base_field, Params > &value)
void write(B &buf, field2< base_field, Params > const &value)
void assert_failure(std::string const &err)
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by MSGPACK_FIEL...
void write(auto &buf, const msgpack_concepts::HasMsgPack auto &obj)
Automatically derived write for any object that defines .msgpack() (implicitly defined by MSGPACK_FIE...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
unsigned __int128 uint128_t
constexpr wnaf_table(const uint256_t &target)
General class for prime fields see Prime field documentation["field documentation"] for general imple...
static constexpr field cube_root_of_unity()
constexpr field(const int input) noexcept
constexpr ~field() noexcept=default
BB_INLINE constexpr field from_montgomery_form_reduced() const noexcept
static constexpr std::array< uint64_t, 9 > wasm_modulus
static constexpr field get_root_of_unity(size_t subgroup_size) noexcept
BB_INLINE constexpr void self_to_montgomery_form_reduced() &noexcept
static constexpr field neg_one()
static constexpr field one()
static constexpr uint256_t modulus
BB_INLINE constexpr void self_reduce_once() &noexcept
static BB_INLINE constexpr std::array< uint64_t, WASM_NUM_LIMBS > wasm_convert(const uint64_t *data)
Convert 4 64-bit limbs into 9 29-bit limbs.
constexpr field(const unsigned long long input) 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....
static BB_INLINE void __swap(field &src, field &dest) noexcept
constexpr field & operator=(const field &other) &noexcept=default
BB_INLINE constexpr void self_from_montgomery_form_reduced() &noexcept
static BB_INLINE constexpr std::pair< uint64_t, uint64_t > mul_wide(uint64_t a, uint64_t b) noexcept
static constexpr uint256_t twice_not_modulus
BB_INLINE constexpr field to_montgomery_form() const noexcept
BB_INLINE constexpr wide_array mul_512(const field &other) const noexcept
static BB_INLINE constexpr uint64_t mac_discard_lo(uint64_t a, uint64_t b, uint64_t c) noexcept
static BB_INLINE constexpr uint64_t sbb(uint64_t a, uint64_t b, uint64_t borrow_in, uint64_t &borrow_out) noexcept
unsigned 64-bit subtract-with-borrow that takes in borrow_in value in the size-2 set {0,...
BB_INLINE constexpr field subtract(const field &other) const noexcept
static constexpr field external_coset_generator()
static void split_into_endomorphism_scalars_384(const field &input, field &k1_out, field &k2_out)
BB_INLINE constexpr void self_conditional_negate(uint64_t predicate) &noexcept
void msgpack_schema(auto &packer) const
static constexpr field tag_coset_generator()
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
static BB_INLINE constexpr uint64_t mac(uint64_t a, uint64_t b, uint64_t c, uint64_t carry_in, uint64_t &carry_out) noexcept
Compute uint128_t(a * b + c + carry_in), where the inputs are all uint64_t. Return the top 64 bits.
static void split_into_endomorphism_scalars(const field &k, field &k1, field &k2)
friend std::ostream & operator<<(std::ostream &os, const field &a)
static BB_INLINE constexpr uint64_t addc(uint64_t a, uint64_t b, uint64_t carry_in, uint64_t &carry_out) noexcept
unsigned 64-bit add-with-carry that takes in a carry_in and a carry_out bit and rewrites the latter.
static constexpr uint256_t r_squared_uint
static BB_INLINE constexpr void wasm_reduce(uint64_t &result_0, uint64_t &result_1, uint64_t &result_2, uint64_t &result_3, uint64_t &result_4, uint64_t &result_5, uint64_t &result_6, uint64_t &result_7, uint64_t &result_8)
Perform 29-bit Montgomery reduction on 1 limb (result_0 should be zero modulo 2^29 after calling this...
BB_INLINE constexpr field montgomery_mul_big(const field &other) const noexcept
Mongtomery multiplication for moduli > 2²⁵⁴
static constexpr size_t COSET_GENERATOR_SIZE
static constexpr size_t PUBLIC_INPUTS_SIZE
constexpr field & operator=(field &&other) &noexcept=default
constexpr field(const uint64_t a, const uint64_t b, const uint64_t c, const uint64_t d) noexcept
cast four uint64_t as a field
constexpr field(const uint128_t &input) noexcept
BB_INLINE constexpr void self_sqr() &noexcept
constexpr field(const uint512_t &input) noexcept
Convert a 512-bit big integer into a field element.
constexpr field invert() const noexcept
constexpr field(field &&other) noexcept=default
BB_INLINE constexpr void self_neg() &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
static BB_INLINE constexpr void wasm_madd(uint64_t &left_limb, const std::array< uint64_t, WASM_NUM_LIMBS > &right_limbs, uint64_t &result_0, uint64_t &result_1, uint64_t &result_2, uint64_t &result_3, uint64_t &result_4, uint64_t &result_5, uint64_t &result_6, uint64_t &result_7, uint64_t &result_8)
Multiply left limb by a sequence of 9 limbs and accumulate into result variables.
static BB_INLINE constexpr uint64_t square_accumulate(uint64_t a, uint64_t b, uint64_t c, uint64_t carry_in_lo, uint64_t carry_in_hi, uint64_t &carry_lo, uint64_t &carry_hi) noexcept
Computes a + 2 * b * c + carry_in_lo + 2^64 * carry_in_hi, in the form of returning a uint64_t and mo...
BB_INLINE constexpr field to_montgomery_form_reduced() const noexcept
BB_INLINE constexpr field conditionally_subtract_from_double_modulus(const uint64_t predicate) const noexcept
constexpr uint256_t uint256_t_no_montgomery_conversion() const noexcept
static constexpr field coset_generator()
static BB_INLINE constexpr void wasm_reduce_yuval(uint64_t &result_0, uint64_t &result_1, uint64_t &result_2, uint64_t &result_3, uint64_t &result_4, uint64_t &result_5, uint64_t &result_6, uint64_t &result_7, uint64_t &result_8, uint64_t &result_9)
Perform 29-bit Montgomery reduction on 1 limb using Yuval's method.
static field serialize_from_buffer(const uint8_t *buffer)
static constexpr uint256_t modulus_minus_two
static void serialize_to_buffer(const field &value, uint8_t *buffer)
void msgpack_pack(auto &packer) const
constexpr std::pair< bool, field > sqrt() const noexcept
Compute square root of the field element.
static BB_INLINE void __copy(const field &a, field &r) noexcept
const uint8_t * vec_in_buf
constexpr field(const field &other) noexcept=default
BB_INLINE constexpr void self_from_montgomery_form() &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.
static constexpr uint256_t not_modulus
BB_INLINE constexpr void self_to_montgomery_form() &noexcept
static constexpr std::array< uint64_t, 9 > wasm_r_inv
BB_INLINE constexpr field from_montgomery_form() const noexcept
BB_INLINE constexpr field operator-() const noexcept
constexpr field(const numeric::uint256_t &input) noexcept
BB_INLINE constexpr void self_set_msb() &noexcept
void msgpack_unpack(auto o)
BB_INLINE constexpr field add(const field &other) const noexcept
BB_INLINE std::vector< uint8_t > to_buffer() const
constexpr field(const unsigned int input) noexcept
static constexpr size_t primitive_root_log_size() noexcept
static field reconstruct_from_public(const std::span< const field< V >, PUBLIC_INPUTS_SIZE > &limbs)
BB_INLINE constexpr field montgomery_square() const noexcept
Squaring via a variant of the Montgomery algorithm, where we roughly take advantage of the repeated t...
BB_INLINE constexpr field reduce_once() const noexcept
BB_INLINE constexpr field montgomery_mul(const field &other) const noexcept
static std::pair< std::array< uint64_t, 2 >, std::array< uint64_t, 2 > > split_into_endomorphism_scalars(const field &k)
BB_INLINE constexpr field reduce() const noexcept
reduce once, i.e., if the value is bigger than the modulus, subtract off the modulus once.
constexpr field(const unsigned long input) noexcept
BB_INLINE constexpr wide_array sqr_512() const noexcept
static constexpr field zero()
static BB_INLINE constexpr uint64_t mac_mini(uint64_t a, uint64_t b, uint64_t c, uint64_t &out) noexcept
BB_INLINE constexpr uint64_t is_msb_set_word() const noexcept
static constexpr uint256_t twice_modulus
constexpr field(std::string input) noexcept
std::size_t operator()(const bb::field< Params > &ff) const noexcept