8#include "../bool/bool.hpp"
9#include "../circuit_builders/circuit_builders.hpp"
18template <
typename Builder>
21 , additive_constant(
bb::
fr::zero())
22 , multiplicative_constant(
bb::
fr::one())
23 , witness_index(IS_CONSTANT)
26template <
typename Builder>
29 , additive_constant(
bb::
fr::zero())
30 , multiplicative_constant(
bb::
fr::one())
31 , witness_index(
value.witness_index)
34template <
typename Builder>
37 , additive_constant(
value)
38 , multiplicative_constant(
bb::
fr::one())
39 , witness_index(IS_CONSTANT)
42template <
typename Builder>
58template <
typename Builder>
86 const bool add_constant_check = (additive_constant ==
bb::fr::zero());
87 const bool mul_constant_check = (multiplicative_constant ==
bb::fr::one());
89 bool result_inverted =
false;
97 uint32_t witness_idx = witness_index;
98 if ((add_constant_check && mul_constant_check) || inverted_check) {
99 result_inverted = inverted_check;
102 witness_idx = get_normalized_witness_index();
108 "Attempting to create a bool_t from a witness_t not satisfying x^2 - x = 0");
112 context->create_bool_gate(witness_idx);
128 if (witness_index == other.
witness_index && !is_constant()) {
142 }
else if (is_constant() && !other.
is_constant()) {
152 bb::fr left = ctx->get_variable(witness_index);
154 bb::fr result_value = left * multiplicative_constant;
156 result_value += additive_constant;
160 ctx->create_add_gate({ .a = witness_index,
163 .a_scaling = multiplicative_constant,
200 }
else if (!is_constant() && other.
is_constant()) {
221 }
else if (is_constant() && !other.
is_constant()) {
263 result_value = left * right;
275 ctx->create_poly_gate({ .a = witness_index,
303 return divide_no_zero_check(other);
331 }
else if (!is_constant() && other.
is_constant()) {
343 }
else if (is_constant() && !other.
is_constant()) {
346 if (get_value() == 0) {
399 bb::fr q_o = -multiplicative_constant;
400 bb::fr q_c = -additive_constant;
422 return field_t(get_value().pow(exponent));
428 bool accumulator_initialized =
false;
431 auto shifted_exponent = exponent;
434 while (shifted_exponent != 0) {
435 if (shifted_exponent & 1) {
436 if (!accumulator_initialized) {
437 accumulator = running_power;
438 accumulator_initialized =
true;
440 accumulator *= running_power;
443 if (shifted_exponent >= 2) {
445 running_power = running_power.
sqr();
447 shifted_exponent >>= 1;
462 return field_t(get_value().pow(exponent_value));
466 return pow(
static_cast<uint32_t
>(exponent_value));
473 for (
size_t i = 0; i < exponent_bits.size(); ++i) {
474 uint256_t value_bit = exponent_value & 1;
478 exponent_bits[31 - i] = bit;
479 exponent_value >>= 1;
483 for (
const auto& bit : exponent_bits) {
484 exponent_accumulator += exponent_accumulator;
485 exponent_accumulator += bit;
488 exponent.
assert_equal(exponent_accumulator,
"field_t::pow exponent accumulator incorrect");
493 for (
size_t i = 0; i < 32; ++i) {
494 accumulator *= accumulator;
496 const field_t multiplier = conditional_assign(exponent_bits[i], *
this, one);
497 accumulator *= multiplier;
511 const bool mul_by_const = is_constant() || to_mul.
is_constant();
516 return ((*
this) * to_mul + to_add);
549 bb::fr out =
a *
b * mul_scaling +
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
553 ctx->create_big_mul_gate({
554 .a = is_constant() ? ctx->zero_idx : witness_index,
558 .mul_scaling = mul_scaling,
559 .a_scaling = a_scaling,
560 .b_scaling = b_scaling,
561 .c_scaling = c_scaling,
563 .const_scaling = const_scaling,
576 if (has_const_summand) {
578 return (*
this) + add_b + add_c;
596 bb::fr a_scaling = multiplicative_constant;
606 bb::fr out =
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
612 ctx->create_big_mul_gate({
613 .a = is_constant() ? ctx->zero_idx : witness_index,
618 .a_scaling = a_scaling,
619 .b_scaling = b_scaling,
620 .c_scaling = c_scaling,
622 .const_scaling = const_scaling,
637 if (is_normalized()) {
662 context->create_add_gate({ .a = witness_index,
665 .a_scaling = multiplicative_constant,
668 .const_scaling = additive_constant });
697 .q_l = multiplicative_constant,
700 .q_c = additive_constant,
740 .q_m = multiplicative_constant,
742 .q_r = additive_constant,
776 bb::fr native_value = get_value();
777 const bool is_zero_raw = native_value.
is_zero();
829 if (!is_constant()) {
831 return (multiplicative_constant *
context->get_variable(witness_index)) + additive_constant;
835 return additive_constant;
843 return ((*
this) - other).is_zero();
851 return !operator==(other);
857template <
typename Builder>
868 static constexpr bb::fr minus_two(-2);
869 return field_t(predicate).
madd(*
this * minus_two, *
this);
883template <
typename Builder>
900 return (lhs - rhs).
madd(predicate, rhs);
907template <
typename Builder>
911 assert_is_zero(
"0-bit range_constraint on non-zero field_t.");
916 context->decompose_into_default_range(
967 const field_t diff = lhs - rhs;
973template <
typename Builder>
977 field_t product = (input - set[0]);
978 for (
size_t i = 1; i < set.size(); i++) {
979 product *= (input - set[i]);
991template <
typename Builder>
1002 table[3] = T3.
add_two(-table[2], -T1);
1009template <
typename Builder>
1024 table[4] = T3.
add_two(-table[2], -T1);
1025 table[5] = T5.
add_two(-table[3], -T1);
1026 table[6] = T6.
add_two(-table[3], -T2);
1027 table[7] = T7.
add_two(-T6 - T5, T4 - table[4]);
1035template <
typename Builder>
1057template <
typename Builder>
1076template <
typename Builder>
1089 ctx->create_big_add_gate({
1090 .a =
a.is_constant() ? ctx->zero_idx :
a.witness_index,
1091 .b =
b.is_constant() ? ctx->zero_idx :
b.witness_index,
1094 .a_scaling =
a.multiplicative_constant,
1095 .b_scaling =
b.multiplicative_constant,
1098 .const_scaling = const_scaling,
1106template <
typename Builder>
1120 bb::fr mul_scaling =
a.multiplicative_constant *
b.multiplicative_constant;
1121 bb::fr a_scaling =
a.multiplicative_constant *
b.additive_constant;
1122 bb::fr b_scaling =
b.multiplicative_constant *
a.additive_constant;
1127 ctx->create_big_mul_gate({
1128 .a =
a.is_constant() ? ctx->zero_idx :
a.witness_index,
1129 .b =
b.is_constant() ? ctx->zero_idx :
b.witness_index,
1132 .mul_scaling = mul_scaling,
1133 .a_scaling = a_scaling,
1134 .b_scaling = b_scaling,
1135 .c_scaling = c_scaling,
1136 .d_scaling = d_scaling,
1137 .const_scaling = const_scaling,
1149 if (input.empty()) {
1153 if (input.size() == 1) {
1154 return input[0].normalize();
1161 for (
const auto&
element : input) {
1165 accumulator.emplace_back(
element);
1168 if (accumulator.empty()) {
1169 return constant_term;
1173 accumulator[0] += constant_term;
1176 Builder* ctx = validate_context<Builder>(accumulator);
1179 size_t num_elements = accumulator.size();
1181 for (
const auto& acc : accumulator) {
1182 output += acc.get_value();
1186 const size_t num_padding_wires = (num_elements % 3) == 0 ? 0 : 3 - (num_elements % 3);
1187 for (
size_t i = 0; i < num_padding_wires; ++i) {
1190 num_elements = accumulator.size();
1191 const size_t num_gates = (num_elements / 3);
1193 const size_t last_gate_idx = num_gates - 1;
1196 field_t accumulating_total = total;
1209 for (
size_t i = 0; i < last_gate_idx; ++i) {
1220 ctx->create_big_add_gate(
1222 .a = accumulator[3 * i].witness_index,
1223 .b = accumulator[3 * i + 1].witness_index,
1224 .c = accumulator[3 * i + 2].witness_index,
1226 .a_scaling = accumulator[3 * i].multiplicative_constant,
1227 .b_scaling = accumulator[3 * i + 1].multiplicative_constant,
1228 .c_scaling = accumulator[3 * i + 2].multiplicative_constant,
1230 .const_scaling = accumulator[3 * i].additive_constant + accumulator[3 * i + 1].additive_constant +
1231 accumulator[3 * i + 2].additive_constant,
1234 bb::fr new_total = accumulating_total.
get_value() - accumulator[3 * i].get_value() -
1235 accumulator[3 * i + 1].get_value() - accumulator[3 * i + 2].get_value();
1241 ctx->create_big_add_gate({
1242 .a = accumulator[3 * last_gate_idx].witness_index,
1243 .b = accumulator[3 * last_gate_idx + 1].witness_index,
1244 .c = accumulator[3 * last_gate_idx + 2].witness_index,
1246 .a_scaling = accumulator[3 * last_gate_idx].multiplicative_constant,
1247 .b_scaling = accumulator[3 * last_gate_idx + 1].multiplicative_constant,
1248 .c_scaling = accumulator[3 * last_gate_idx + 2].multiplicative_constant,
1250 .const_scaling = accumulator[3 * last_gate_idx].additive_constant +
1251 accumulator[3 * last_gate_idx + 1].additive_constant +
1252 accumulator[3 * last_gate_idx + 2].additive_constant,
1255 for (
const auto& single_input : input) {
1256 new_tag =
OriginTag(new_tag, single_input.tag);
1258 total.
tag = new_tag;
1267template <
typename Builder>
1269 const size_t num_bits)
const
1271 ASSERT(lsb_index < num_bits);
1278 if (is_constant()) {
1285 if (lsb_index == 0) {
1288 create_range_constraint(num_bits,
"split_at: hi value too large.");
1306 assert_equal(reconstructed,
"split_at: decomposition failed");
#define BB_ASSERT_EQ(actual, expected,...)
#define BB_ASSERT_LT(left, right,...)
#define ASSERT(expression,...)
static constexpr size_t DEFAULT_PLOOKUP_RANGE_BITNUM
constexpr uint64_t get_msb() const
Implements boolean logic in-circuit.
void set_origin_tag(const OriginTag &new_tag) const
OriginTag get_origin_tag() const
void assert_is_zero(std::string const &msg="field_t::assert_is_zero") const
Enforce a copy constraint between *this and 0 stored at zero_idx of the Builder.
field_t conditional_negate(const bool_t< Builder > &predicate) const
If predicate's value == true, negate the value, else keep it unchanged.
void assert_is_in_set(const std::vector< field_t > &set, std::string const &msg="field_t::assert_not_in_set") const
Constrain *this \in set by enforcing that P(X) = \prod_{s \in set} (X - s) is 0 at X = *this.
void assert_equal(const field_t &rhs, std::string const &msg="field_t::assert_equal") const
Copy constraint: constrain that *this field is equal to rhs element.
void assert_not_equal(const field_t &rhs, std::string const &msg="field_t::assert_not_equal") const
Constrain *this to be not equal to rhs.
bool is_normalized() const
field_t madd(const field_t &to_mul, const field_t &to_add) const
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
field_t operator+(const field_t &other) const
Field addition operator.
bool_t< Builder > operator!=(const field_t &other) const
Compute a bool_t equal to (a != b)
static field_t select_from_three_bit_table(const std::array< field_t, 8 > &table, const bool_t< Builder > &t2, const bool_t< Builder > &t1, const bool_t< Builder > &t0)
Given a multilinear polynomial in 3 variables, which is represented by a table of monomial coefficien...
static field_t accumulate(const std::vector< field_t > &input)
Efficiently compute the sum of vector entries. Using big_add_gate we reduce the number of gates neede...
static void evaluate_polynomial_identity(const field_t &a, const field_t &b, const field_t &c, const field_t &d)
Given a, b, c, d, constrain a * b + c + d = 0 by creating a big_mul_gate.
field_t operator-() const
void create_range_constraint(size_t num_bits, std::string const &msg="field_t::range_constraint") const
Let x = *this.normalize(), constrain x.v < 2^{num_bits}.
static field_t conditional_assign(const bool_t< Builder > &predicate, const field_t &lhs, const field_t &rhs)
If predicate == true then return lhs, else return rhs.
field_t divide_no_zero_check(const field_t &other) const
Given field elements a = *this and b = other, output a / b without checking whether b = 0.
static std::array< field_t, 8 > preprocess_three_bit_table(const field_t &T0, const field_t &T1, const field_t &T2, const field_t &T3, const field_t &T4, const field_t &T5, const field_t &T6, const field_t &T7)
Given a table T of size 8, outputs the monomial coefficients of the multilinear polynomial in t0,...
bb::fr multiplicative_constant
Builder * get_context() const
std::pair< field_t< Builder >, field_t< Builder > > split_at(const size_t lsb_index, const size_t num_bits=grumpkin::MAX_NO_WRAP_INTEGER_BIT_LENGTH) const
Splits the field element into (lo, hi), where:
OriginTag get_origin_tag() const
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
field_t operator*(const field_t &other) const
Field multiplication operator.
field_t(Builder *parent_context=nullptr)
field_t normalize() const
Return a new element, where the in-circuit witness contains the actual represented value (multiplicat...
static field_t select_from_two_bit_table(const std::array< field_t, 4 > &table, const bool_t< Builder > &t1, const bool_t< Builder > &t0)
Given a multilinear polynomial in 2 variables, which is represented by a table of monomial coefficien...
static void evaluate_linear_identity(const field_t &a, const field_t &b, const field_t &c, const field_t &d)
Constrain a + b + c + d to be equal to 0.
bool_t< Builder > is_zero() const
Validate whether a field_t element is zero.
field_t pow(const uint32_t &exponent) const
Raise this field element to the power of the provided uint32_t exponent.
static std::array< field_t, 4 > preprocess_two_bit_table(const field_t &T0, const field_t &T1, const field_t &T2, const field_t &T3)
Given a table T of size 4, outputs the monomial coefficients of the multilinear polynomial in t0,...
uint32_t get_normalized_witness_index() const
Get the index of a normalized version of this element.
void set_origin_tag(const OriginTag &new_tag) const
field_t add_two(const field_t &add_b, const field_t &add_c) const
Efficiently compute (this + a + b) using big_mul gate.
void assert_is_not_zero(std::string const &msg="field_t::assert_is_not_zero") const
Constrain *this to be non-zero by establishing that it has an inverse.
field_t operator/(const field_t &other) const
Since in divide_no_zero_check, we check by the constraint , if , we can set to any value and it wil...
bool_t< Builder > operator==(const field_t &other) const
Compute a bool_t equal to (a == b)
uint32_t get_witness_index() const
Get the witness index of the current field element.
StrictMock< MockContext > context
constexpr size_t MAX_NO_WRAP_INTEGER_BIT_LENGTH
constexpr T get_msb(const T in)
T * validate_context(T *ptr)
std::conditional_t< IsGoblinBigGroup< C, Fq, Fr, G >, element_goblin::goblin_element< C, goblin_field< C >, Fr, G >, element_default::element< C, Fq, Fr, G > > element
element wraps either element_default::element or element_goblin::goblin_element depending on parametr...
Entry point for Barretenberg command-line interface.
Univariate< Fr, domain_end, domain_start, skip_count > operator+(const Fr &ff, const Univariate< Fr, domain_end, domain_start, skip_count > &uv)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static constexpr field neg_one()
static constexpr field one()
constexpr field invert() const noexcept
BB_INLINE constexpr void self_neg() &noexcept
BB_INLINE constexpr bool is_zero() const noexcept
static constexpr field zero()