3#include "barretenberg/ecc/curves/bn254/fq.hpp"
4#include "barretenberg/ecc/curves/bn254/fr.hpp"
5#include "barretenberg/numeric/uint256/uint256.hpp"
6#include "barretenberg/numeric/uintx/uintx.hpp"
7#include "barretenberg/plonk/proof_system/constants.hpp"
9#include "../byte_array/byte_array.hpp"
10#include "../field/field.hpp"
12#include "../circuit_builders/circuit_builders_fwd.hpp"
17template <
typename Builder,
typename T>
class bigfield {
38 maximum_value = DEFAULT_MAXIMUM_LIMB;
41 friend std::ostream& operator<<(std::ostream& os,
const Limb& a)
43 os <<
"{ " << a.element <<
" < " << a.maximum_value <<
" }";
48 Limb& operator=(
const Limb& other) =
default;
49 Limb& operator=(
Limb&& other) =
default;
57 const bool can_overflow =
false,
58 const size_t maximum_bitlength = 0);
67 const bool can_overflow =
false)
73 binary_basis_limbs[3] =
74 Limb(
field_t(d), can_overflow ? DEFAULT_MAXIMUM_LIMB : DEFAULT_MAXIMUM_MOST_SIGNIFICANT_LIMB);
76 (binary_basis_limbs[3].element * shift_3)
77 .add_two(binary_basis_limbs[2].
element * shift_2, binary_basis_limbs[1].
element * shift_1);
78 prime_basis_limb += (binary_basis_limbs[0].element);
87 const bool can_overflow =
false)
90 binary_basis_limbs[0] = Limb(
field_t(a));
91 binary_basis_limbs[1] = Limb(
field_t(b));
92 binary_basis_limbs[2] = Limb(
field_t(c));
93 binary_basis_limbs[3] =
94 Limb(
field_t(d), can_overflow ? DEFAULT_MAXIMUM_LIMB : DEFAULT_MAXIMUM_MOST_SIGNIFICANT_LIMB);
95 prime_basis_limb = prime_limb;
98 bigfield(
const byte_array<Builder>& bytes);
99 bigfield(
const bigfield& other);
100 bigfield(bigfield&& other);
103 const uint512_t& value,
104 const bool can_overflow =
false,
105 const size_t maximum_bitlength = 0);
113 return bigfield(low, hi);
116 bigfield& operator=(
const bigfield& other);
117 bigfield& operator=(bigfield&& other);
119 static constexpr uint256_t modulus = (
uint256_t(T::modulus_0, T::modulus_1, T::modulus_2, T::modulus_3));
120 static constexpr uint512_t modulus_u512 = uint512_t(modulus);
121 static constexpr uint64_t NUM_LIMB_BITS = NUM_LIMB_BITS_IN_FIELD_SIMULATION;
122 static constexpr uint64_t NUM_LAST_LIMB_BITS = modulus_u512.get_msb() + 1 - (NUM_LIMB_BITS * 3);
123 static constexpr uint1024_t DEFAULT_MAXIMUM_REMAINDER =
124 (uint1024_t(1) << (NUM_LIMB_BITS * 3 + NUM_LAST_LIMB_BITS)) - uint1024_t(1);
126 static constexpr uint256_t DEFAULT_MAXIMUM_MOST_SIGNIFICANT_LIMB =
128 static constexpr uint64_t LOG2_BINARY_MODULUS = NUM_LIMB_BITS * 4;
129 static constexpr bool is_composite =
true;
131 static constexpr uint256_t prime_basis_maximum_limb =
132 uint256_t(modulus_u512.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4));
133 static constexpr Basis prime_basis{ uint512_t(barretenberg::fr::modulus), barretenberg::fr::modulus.get_msb() + 1 };
134 static constexpr Basis binary_basis{ uint512_t(1) << LOG2_BINARY_MODULUS, LOG2_BINARY_MODULUS };
135 static constexpr Basis target_basis{ modulus_u512, modulus_u512.get_msb() + 1 };
143 static constexpr uint512_t negative_prime_modulus = binary_basis.modulus - target_basis.modulus;
144 static constexpr uint256_t neg_modulus_limbs_u256[4]{
145 uint256_t(negative_prime_modulus.slice(0, NUM_LIMB_BITS).lo),
146 uint256_t(negative_prime_modulus.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2).lo),
147 uint256_t(negative_prime_modulus.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3).lo),
148 uint256_t(negative_prime_modulus.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4).lo),
152 barretenberg::fr(negative_prime_modulus.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2).lo),
153 barretenberg::fr(negative_prime_modulus.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3).lo),
154 barretenberg::fr(negative_prime_modulus.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4).lo),
157 byte_array<Builder> to_byte_array()
const
159 byte_array<Builder> result(get_context());
160 field_t<Builder> lo = binary_basis_limbs[0].element + (binary_basis_limbs[1].element * shift_1);
161 field_t<Builder> hi = binary_basis_limbs[2].element + (binary_basis_limbs[3].element * shift_1);
169 ASSERT((NUM_LIMB_BITS * 2 / 8) * 8 == NUM_LIMB_BITS * 2);
170 result.write(byte_array<Builder>(hi, 32 - (NUM_LIMB_BITS / 4)));
171 result.write(byte_array<Builder>(lo, (NUM_LIMB_BITS / 4)));
175 uint512_t get_value()
const;
176 uint512_t get_maximum_value()
const;
179 bigfield operator+(
const bigfield& other)
const;
180 bigfield
operator-(
const bigfield& other)
const;
181 bigfield
operator*(
const bigfield& other)
const;
193 *
this = operator+(other);
196 bigfield operator-=(
const bigfield& other)
198 *
this = operator-(other);
201 bigfield operator*=(
const bigfield& other)
206 bigfield operator/=(
const bigfield& other)
212 bigfield
sqr()
const;
213 bigfield
sqradd(
const std::vector<bigfield>& to_add)
const;
214 bigfield
madd(
const bigfield& to_mul,
const std::vector<bigfield>& to_add)
const;
217 std::vector<bigfield>& mul_right,
218 const std::vector<bigfield>& to_add);
220 static bigfield
mult_madd(
const std::vector<bigfield>& mul_left,
221 const std::vector<bigfield>& mul_right,
222 const std::vector<bigfield>& to_add,
223 bool fix_remainder_to_zero =
false);
225 static bigfield
dual_madd(
const bigfield& left_a,
226 const bigfield& right_a,
227 const bigfield& left_b,
228 const bigfield& right_b,
229 const std::vector<bigfield>& to_add);
233 static bigfield
msub_div(
const std::vector<bigfield>& mul_left,
234 const std::vector<bigfield>& mul_right,
235 const bigfield& divisor,
236 const std::vector<bigfield>& to_sub,
237 bool enable_divisor_nz_check =
false);
239 static bigfield
sum(
const std::vector<bigfield>& terms);
240 static bigfield
internal_div(
const std::vector<bigfield>& numerators,
241 const bigfield& denominator,
242 bool check_for_zero);
247 bigfield conditional_negate(
const bool_t<Builder>& predicate)
const;
248 bigfield
conditional_select(
const bigfield& other,
const bool_t<Builder>& predicate)
const;
250 void assert_is_in_field()
const;
251 void assert_less_than(
const uint256_t upper_limit)
const;
252 void assert_equal(
const bigfield& other)
const;
253 void assert_is_not_equal(
const bigfield& other)
const;
255 void self_reduce()
const;
257 bool is_constant()
const {
return prime_basis_limb.witness_index == IS_CONSTANT; }
285 uint512_t multiple_of_modulus = ((get_maximum_unreduced_value() / modulus_u512) + 1) * modulus_u512;
286 auto msb = multiple_of_modulus.get_msb();
289 result.binary_basis_limbs[0] =
Limb(
barretenberg::fr(multiple_of_modulus.slice(0, NUM_LIMB_BITS).lo));
290 result.binary_basis_limbs[1] =
292 result.binary_basis_limbs[2] =
294 result.binary_basis_limbs[3] =
Limb(
barretenberg::fr(multiple_of_modulus.slice(3 * NUM_LIMB_BITS, msb + 1).lo));
305 for (
auto& limb : binary_basis_limbs) {
306 limb.element.convert_constant_to_fixed_witness(context);
308 prime_basis_limb.convert_constant_to_fixed_witness(context);
316 for (
auto& limb : binary_basis_limbs) {
317 limb.element.fix_witness();
319 prime_basis_limb.fix_witness();
322 Builder* get_context()
const {
return context; }
324 static constexpr uint512_t get_maximum_unreduced_value(
const size_t num_products = 1)
327 uint1024_t maximum_product = uint1024_t(binary_basis.modulus) * uint1024_t(prime_basis.modulus) /
328 uint1024_t(
static_cast<uint64_t
>(num_products));
330 uint64_t maximum_product_bits = maximum_product.get_msb() - 1;
331 return (uint512_t(1) << (maximum_product_bits >> 1)) - uint512_t(1);
334 static constexpr uint1024_t get_maximum_crt_product()
336 uint1024_t maximum_product = uint1024_t(binary_basis.modulus) * uint1024_t(prime_basis.modulus);
337 return maximum_product;
349 uint1024_t base = get_maximum_crt_product();
350 for (
const auto& r : remainders_max) {
353 base /= modulus_u512;
354 return static_cast<size_t>(base.get_msb() - 1);
367 const uint1024_t& b_max,
368 const std::vector<bigfield>& to_add)
370 uint1024_t product = a_max * b_max;
372 for (
const auto& add : to_add) {
373 add_term += add.get_maximum_value();
375 constexpr uint1024_t maximum_default_bigint = uint1024_t(1) << (NUM_LIMB_BITS * 6 + NUM_LAST_LIMB_BITS * 2);
379 ASSERT(add_term + maximum_default_bigint < get_maximum_crt_product());
380 return ((product + add_term) >= get_maximum_crt_product());
393 const std::vector<uint512_t>& bs_max,
394 const std::vector<bigfield>& to_add)
396 std::vector<uint1024_t> products;
397 ASSERT(as_max.size() == bs_max.size());
399 uint1024_t product_sum;
401 for (
size_t i = 0; i < as_max.size(); i++) {
402 product_sum += uint1024_t(as_max[i]) * uint1024_t(bs_max[i]);
404 for (
const auto& add : to_add) {
405 add_term += add.get_maximum_value();
407 constexpr uint1024_t maximum_default_bigint = uint1024_t(1) << (NUM_LIMB_BITS * 6 + NUM_LAST_LIMB_BITS * 2);
411 ASSERT(add_term + maximum_default_bigint < get_maximum_crt_product());
412 return ((product_sum + add_term) >= get_maximum_crt_product());
430 static constexpr uint64_t MAX_ADDITION_LOG = 10;
433 static constexpr uint64_t MAX_UNREDUCED_LIMB_SIZE =
434 (barretenberg::fr::modulus.get_msb() + 1) / 2 - MAX_ADDITION_LOG;
436 static constexpr uint256_t get_maximum_unreduced_limb_value() {
return uint256_t(1) << MAX_UNREDUCED_LIMB_SIZE; }
438 static_assert(MAX_UNREDUCED_LIMB_SIZE < (NUM_LIMB_BITS * 2));
440 mutable Limb binary_basis_limbs[4];
444 static std::pair<uint512_t, uint512_t> compute_quotient_remainder_values(
const bigfield& a,
446 const std::vector<bigfield>& to_add);
455 static uint512_t compute_maximum_quotient_value(
const std::vector<uint512_t>& as,
456 const std::vector<uint512_t>& bs,
457 const std::vector<uint512_t>& to_add);
469 static std::pair<bool, size_t> get_quotient_reduction_info(
const std::vector<uint512_t>& as_max,
470 const std::vector<uint512_t>& bs_max,
471 const std::vector<bigfield>& to_add,
472 const std::vector<uint1024_t>& remainders_max = {
473 DEFAULT_MAXIMUM_REMAINDER });
475 static void unsafe_evaluate_multiply_add(
const bigfield& left,
476 const bigfield& right_mul,
477 const std::vector<bigfield>& to_add,
478 const bigfield& quotient,
479 const std::vector<bigfield>& remainders);
481 static void unsafe_evaluate_multiple_multiply_add(
const std::vector<bigfield>& input_left,
482 const std::vector<bigfield>& input_right,
483 const std::vector<bigfield>& to_add,
484 const bigfield& input_quotient,
485 const std::vector<bigfield>& input_remainders);
487 static void unsafe_evaluate_square_add(
const bigfield& left,
488 const std::vector<bigfield>& to_add,
489 const bigfield& quotient,
490 const bigfield& remainder);
492 static void evaluate_product(
const bigfield& left,
493 const bigfield& right,
494 const bigfield& quotient,
495 const bigfield& remainder);
496 void reduction_check(
const size_t num_products = 1)
const;
500template <
typename C,
typename T>
inline std::ostream& operator<<(std::ostream& os, bigfield<T, C>
const& v)
502 return os << v.get_value();
508#include "bigfield_impl.hpp"
Definition: uint256.hpp:25
Definition: standard_circuit_builder.hpp:12
Definition: bigfield.hpp:17
bigfield madd(const bigfield &to_mul, const std::vector< bigfield > &to_add) const
Definition: bigfield_impl.hpp:972
static bigfield dual_madd(const bigfield &left_a, const bigfield &right_a, const bigfield &left_b, const bigfield &right_b, const std::vector< bigfield > &to_add)
Definition: bigfield_impl.hpp:1337
bigfield bad_mul(const bigfield &other) const
bigfield operator/(const bigfield &other) const
Definition: bigfield_impl.hpp:727
static bool mul_product_overflows_crt_modulus(const std::vector< uint512_t > &as_max, const std::vector< uint512_t > &bs_max, const std::vector< bigfield > &to_add)
Definition: bigfield.hpp:392
bigfield operator*(const bigfield &other) const
Definition: bigfield_impl.hpp:681
static constexpr bigfield unreduced_zero()
Create an unreduced 0 ~ p*k, where p*k is the minimal multiple of modulus that should be reduced.
Definition: bigfield.hpp:283
bigfield operator-(const bigfield &other) const
Definition: bigfield_impl.hpp:477
bigfield sqradd(const std::vector< bigfield > &to_add) const
Definition: bigfield_impl.hpp:904
static bigfield mult_madd(const std::vector< bigfield > &mul_left, const std::vector< bigfield > &mul_right, const std::vector< bigfield > &to_add, bool fix_remainder_to_zero=false)
Definition: bigfield_impl.hpp:1167
static void perform_reductions_for_mult_madd(std::vector< bigfield > &mul_left, std::vector< bigfield > &mul_right, const std::vector< bigfield > &to_add)
Performs individual reductions on the supplied elements as well as more complex reductions to prevent...
Definition: bigfield_impl.hpp:1035
static bigfield create_from_u512_as_witness(Builder *ctx, const uint512_t &value, const bool can_overflow=false, const size_t maximum_bitlength=0)
Creates a bigfield element from a uint512_t. Bigfield element is constructed as a witness and not a c...
Definition: bigfield_impl.hpp:176
static size_t get_quotient_max_bits(const std::vector< uint1024_t > &remainders_max)
Compute the maximum number of bits for quotient range proof to protect against CRT underflow.
Definition: bigfield.hpp:346
static bigfield div_without_denominator_check(const std::vector< bigfield > &numerators, const bigfield &denominator)
Definition: bigfield_impl.hpp:842
static bigfield sum(const std::vector< bigfield > &terms)
Create constraints for summing these terms.
Definition: bigfield_impl.hpp:741
bigfield sqr() const
Definition: bigfield_impl.hpp:866
static bool mul_product_overflows_crt_modulus(const uint1024_t &a_max, const uint1024_t &b_max, const std::vector< bigfield > &to_add)
Definition: bigfield.hpp:366
static bigfield msub_div(const std::vector< bigfield > &mul_left, const std::vector< bigfield > &mul_right, const bigfield &divisor, const std::vector< bigfield > &to_sub, bool enable_divisor_nz_check=false)
Definition: bigfield_impl.hpp:1373
bigfield conditional_select(const bigfield &other, const bool_t< Builder > &predicate) const
Create an element which is equal to either this or other based on the predicate.
Definition: bigfield_impl.hpp:1530
void convert_constant_to_fixed_witness(Builder *builder)
Definition: bigfield.hpp:302
void fix_witness()
Definition: bigfield.hpp:314
static bigfield div_check_denominator_nonzero(const std::vector< bigfield > &numerators, const bigfield &denominator)
Definition: bigfield_impl.hpp:856
static bigfield zero()
Definition: bigfield.hpp:271
bigfield add_to_lower_limb(const field_t< Builder > &other, uint256_t other_maximum_value) const
Add a field element to the lower limb. CAUTION (the element has to be constrained before using this f...
Definition: bigfield_impl.hpp:349
static bigfield internal_div(const std::vector< bigfield > &numerators, const bigfield &denominator, bool check_for_zero)
Definition: bigfield_impl.hpp:768
static bigfield one()
Definition: bigfield.hpp:262
Definition: biggroup.hpp:22
barretenberg::fr additive_constant
Definition: field.hpp:379
uint32_t witness_index
Definition: field.hpp:423
Definition: witness.hpp:10
Definition: widget.bench.cpp:13
Definition: field_declarations.hpp:24
Definition: bigfield.hpp:23
Definition: bigfield.hpp:28