9#include "../bool/bool.hpp"
10#include "../circuit_builders/circuit_builders.hpp"
20template <
typename Builder>
23 , additive_constant(
bb::
fr::zero())
24 , multiplicative_constant(
bb::
fr::one())
25 , witness_index(IS_CONSTANT)
30template <
typename Builder>
33 , additive_constant(
bb::
fr::zero())
34 , multiplicative_constant(
bb::
fr::one())
35 , witness_index(
value.witness_index)
40template <
typename Builder>
43 , additive_constant(
value)
44 , multiplicative_constant(
bb::
fr::one())
45 , witness_index(IS_CONSTANT)
50template <
typename Builder>
66template <
typename Builder>
91 "Attempting to create a bool_t from a witness_t not satisfying x^2 - x = 0");
98 const bool add_constant_check = (additive_constant ==
bb::fr::zero());
99 const bool mul_constant_check = (multiplicative_constant ==
bb::fr::one());
101 bool result_inverted =
false;
109 uint32_t witness_idx = witness_index;
110 if ((add_constant_check && mul_constant_check) || inverted_check) {
111 result_inverted = inverted_check;
119 "Attempting to create a bool_t from a witness_t not satisfying x^2 - x = 0");
123 context->create_bool_gate(witness_idx);
139 if (witness_indices_match(*
this, other) && !is_constant()) {
148 }
else if (!is_constant() && other.
is_constant()) {
153 }
else if (is_constant() && !other.
is_constant()) {
163 bb::fr left = ctx->get_variable(witness_index);
165 bb::fr result_value = left * multiplicative_constant;
167 result_value += additive_constant;
171 ctx->create_add_gate({ .a = witness_index,
174 .a_scaling = multiplicative_constant,
188 rhs.additive_constant.self_neg();
189 if (!rhs.is_constant()) {
191 rhs.multiplicative_constant.self_neg();
274 result_value = left * right;
286 ctx->create_arithmetic_gate({ .a = witness_index,
314 return divide_no_zero_check(other);
342 }
else if (!is_constant() && other.
is_constant()) {
354 }
else if (is_constant() && !other.
is_constant()) {
357 if (get_value() == 0) {
362 bb::fr numerator = get_value();
364 denominator_inv = denominator_inv.
is_zero() ? 0 : denominator_inv.
invert();
366 bb::fr out(numerator * denominator_inv);
374 bb::fr q_c = -get_value();
392 denominator_inv = denominator_inv.
is_zero() ? 0 : denominator_inv.
invert();
410 bb::fr q_o = -multiplicative_constant;
433 return field_t(get_value().pow(exponent));
439 bool accumulator_initialized =
false;
442 auto shifted_exponent = exponent;
445 while (shifted_exponent != 0) {
446 if (shifted_exponent & 1) {
447 if (!accumulator_initialized) {
448 accumulator = running_power;
449 accumulator_initialized =
true;
451 accumulator *= running_power;
454 if (shifted_exponent >= 2) {
456 running_power = running_power.
sqr();
458 shifted_exponent >>= 1;
467template <
typename Builder>
468template <
size_t num_bits>
475 return field_t(get_value().pow(exponent_value));
479 return pow(
static_cast<uint32_t
>(exponent_value));
486 for (
size_t i = 0; i < exponent_bits.size(); ++i) {
487 uint256_t value_bit = exponent_value & 1;
491 exponent_bits[num_bits - 1 - i] = bit;
492 exponent_value >>= 1;
496 for (
const auto& bit : exponent_bits) {
497 exponent_accumulator += exponent_accumulator;
498 exponent_accumulator += bit;
501 exponent.
assert_equal(exponent_accumulator,
"field_t::pow exponent accumulator incorrect");
506 for (
size_t i = 0; i < num_bits; ++i) {
507 accumulator *= accumulator;
509 const field_t multiplier = conditional_assign_internal(exponent_bits[i], *
this, one);
510 accumulator *= multiplier;
524 const bool mul_by_const = is_constant() || to_mul.
is_constant();
529 return ((*
this) * to_mul + to_add);
562 bb::fr out =
a *
b * mul_scaling +
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
566 ctx->create_big_mul_add_gate({
567 .a = is_constant() ? ctx->zero_idx() : witness_index,
571 .mul_scaling = mul_scaling,
572 .a_scaling = a_scaling,
573 .b_scaling = b_scaling,
574 .c_scaling = c_scaling,
576 .const_scaling = const_scaling,
589 if (has_const_summand) {
591 return (*
this) + add_b + add_c;
609 bb::fr a_scaling = multiplicative_constant;
619 bb::fr out =
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
625 ctx->create_big_mul_add_gate({
626 .a = is_constant() ? ctx->zero_idx() : witness_index,
631 .a_scaling = a_scaling,
632 .b_scaling = b_scaling,
633 .c_scaling = c_scaling,
635 .const_scaling = const_scaling,
650 if (is_normalized()) {
675 context->create_add_gate({ .a = witness_index,
678 .a_scaling = multiplicative_constant,
681 .const_scaling = additive_constant });
705 context->create_arithmetic_gate({
710 .q_l = multiplicative_constant,
713 .q_c = additive_constant,
747 context->create_arithmetic_gate({
751 .q_m = multiplicative_constant,
753 .q_r = additive_constant,
787 bb::fr native_value = get_value();
788 const bool is_zero_raw = native_value.
is_zero();
840 if (!is_constant()) {
842 return (multiplicative_constant *
context->get_variable(witness_index)) + additive_constant;
846 return additive_constant;
854 return ((*
this) - other).is_zero();
862 return !operator==(other);
868template <
typename Builder>
879 static constexpr bb::fr minus_two(-2);
880 return field_t(predicate).
madd(*
this * minus_two, *
this);
894template <
typename Builder>
906 if (witness_indices_match(lhs, rhs) && (lhs.
additive_constant == rhs.additive_constant) &&
913 return (lhs - rhs).
madd(predicate, rhs);
920template <
typename Builder>
924 assert_is_zero(
"0-bit range_constraint on non-zero field_t.");
929 context->create_limbed_range_constraint(
951 ctx->assert_equal_constant(rhs.get_witness_index(), lhs.
get_value(), msg);
952 }
else if (rhs.is_constant()) {
958 const auto rhs_original_tag = rhs.get_origin_tag();
961 rhs.set_origin_tag(empty_tag);
969 .b = rhs.witness_index,
970 .c = ctx->zero_idx(),
972 .b_scaling = -rhs.multiplicative_constant,
975 if ((lhs.
get_value() != rhs.get_value()) && !ctx->failed()) {
982 rhs.set_origin_tag(rhs_original_tag);
991 const field_t diff = lhs - rhs;
997template <
typename Builder>
1001 field_t product = (input - set[0]);
1002 for (
size_t i = 1; i < set.size(); i++) {
1003 product *= (input - set[i]);
1015template <
typename Builder>
1026 table[3] = T3.
add_two(-table[2], -T1);
1033template <
typename Builder>
1048 table[4] = T3.
add_two(-table[2], -T1);
1049 table[5] = T5.
add_two(-table[3], -T1);
1050 table[6] = T6.
add_two(-table[3], -T2);
1051 table[7] = T7.
add_two(-T6 - T5, T4 - table[4]);
1059template <
typename Builder>
1081template <
typename Builder>
1100template <
typename Builder>
1111 const bool identity_holds = (
a.get_value() +
b.get_value() + c.
get_value() + d.
get_value()).is_zero();
1112 if (!identity_holds && !ctx->failed()) {
1119 ctx->create_big_add_gate({
1120 .a =
a.is_constant() ? ctx->zero_idx() :
a.witness_index,
1121 .b =
b.is_constant() ? ctx->zero_idx() :
b.witness_index,
1124 .a_scaling =
a.multiplicative_constant,
1125 .b_scaling =
b.multiplicative_constant,
1128 .const_scaling = const_scaling,
1136template <
typename Builder>
1147 const bool identity_holds = ((
a.get_value() *
b.get_value()) + c.
get_value() + d.
get_value()).is_zero();
1148 if (!identity_holds && !ctx->failed()) {
1153 bb::fr mul_scaling =
a.multiplicative_constant *
b.multiplicative_constant;
1154 bb::fr a_scaling =
a.multiplicative_constant *
b.additive_constant;
1155 bb::fr b_scaling =
b.multiplicative_constant *
a.additive_constant;
1160 ctx->create_big_mul_add_gate({
1161 .a =
a.is_constant() ? ctx->zero_idx() :
a.witness_index,
1162 .b =
b.is_constant() ? ctx->zero_idx() :
b.witness_index,
1165 .mul_scaling = mul_scaling,
1166 .a_scaling = a_scaling,
1167 .b_scaling = b_scaling,
1168 .c_scaling = c_scaling,
1169 .d_scaling = d_scaling,
1170 .const_scaling = const_scaling,
1182 if (input.empty()) {
1186 if (input.size() == 1) {
1187 return input[0].normalize();
1194 for (
const auto&
element : input) {
1198 accumulator.emplace_back(
element);
1201 if (accumulator.empty()) {
1202 return constant_term;
1206 accumulator[0] += constant_term;
1209 Builder* ctx = validate_context<Builder>(accumulator);
1212 size_t num_elements = accumulator.size();
1214 for (
const auto& acc : accumulator) {
1215 output += acc.get_value();
1219 const size_t num_padding_wires = (num_elements % 3) == 0 ? 0 : 3 - (num_elements % 3);
1220 for (
size_t i = 0; i < num_padding_wires; ++i) {
1223 num_elements = accumulator.size();
1224 const size_t num_gates = (num_elements / 3);
1226 const size_t last_gate_idx = num_gates - 1;
1229 field_t accumulating_total = total;
1242 for (
size_t i = 0; i < last_gate_idx; ++i) {
1253 ctx->create_big_add_gate(
1255 .a = accumulator[3 * i].witness_index,
1256 .b = accumulator[3 * i + 1].witness_index,
1257 .c = accumulator[3 * i + 2].witness_index,
1259 .a_scaling = accumulator[3 * i].multiplicative_constant,
1260 .b_scaling = accumulator[3 * i + 1].multiplicative_constant,
1261 .c_scaling = accumulator[3 * i + 2].multiplicative_constant,
1263 .const_scaling = accumulator[3 * i].additive_constant + accumulator[3 * i + 1].additive_constant +
1264 accumulator[3 * i + 2].additive_constant,
1267 bb::fr new_total = accumulating_total.
get_value() - accumulator[3 * i].get_value() -
1268 accumulator[3 * i + 1].get_value() - accumulator[3 * i + 2].get_value();
1274 ctx->create_big_add_gate({
1275 .a = accumulator[3 * last_gate_idx].witness_index,
1276 .b = accumulator[3 * last_gate_idx + 1].witness_index,
1277 .c = accumulator[3 * last_gate_idx + 2].witness_index,
1279 .a_scaling = accumulator[3 * last_gate_idx].multiplicative_constant,
1280 .b_scaling = accumulator[3 * last_gate_idx + 1].multiplicative_constant,
1281 .c_scaling = accumulator[3 * last_gate_idx + 2].multiplicative_constant,
1283 .const_scaling = accumulator[3 * last_gate_idx].additive_constant +
1284 accumulator[3 * last_gate_idx + 1].additive_constant +
1285 accumulator[3 * last_gate_idx + 2].additive_constant,
1288 for (
const auto& single_input : input) {
1289 new_tag =
OriginTag(new_tag, single_input.tag);
1291 total.
tag = new_tag;
1303template <
typename Builder>
1305 const size_t num_bits)
const
1314 if (is_constant()) {
1321 if (lsb_index == 0) {
1324 create_range_constraint(num_bits,
"split_at: hi value too large.");
1342 assert_equal(reconstructed,
"split_at: decomposition failed");
#define BB_ASSERT(expression,...)
#define BB_ASSERT_DEBUG(expression,...)
#define BB_ASSERT_EQ(actual, expected,...)
#define BB_ASSERT_LT(left, right,...)
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
uint32_t witness_index
Index of the witness in the builder's witness vector.
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 void evaluate_polynomial_identity(const field_t &a, const field_t &b, const field_t &c, const field_t &d, const std::string &msg="field_t::evaluate_polynomial_identity")
Given a, b, c, d, constrain a * b + c + d = 0 by creating a big_mul_gate.
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...
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}.
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
static field_t conditional_assign_internal(const bool_t< Builder > &predicate, const field_t &lhs, const field_t &rhs)
If predicate == true then return lhs, else return rhs.
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...
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 void evaluate_linear_identity(const field_t &a, const field_t &b, const field_t &c, const field_t &d, const std::string &msg="field_t::evaluate_linear_identity")
Constrain a + b + c + d to be equal to 0.
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,...
void set_free_witness_tag()
Set the free witness flag for the field element's tag.
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.
std::pair< field_t< Builder >, field_t< Builder > > no_wrap_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:
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...
void mark_witness_as_used(const field_t< Builder > &field)
Mark a field_t witness as used (for UltraBuilder only).
Entry point for Barretenberg command-line interface.
Univariate< Fr, domain_end > operator+(const Fr &ff, const Univariate< Fr, domain_end > &uv)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static OriginTag constant()
static constexpr field neg_one()
static constexpr field one()
constexpr field invert() const noexcept
BB_INLINE constexpr bool is_zero() const noexcept
static constexpr field zero()