8#include "../bool/bool.hpp"
9#include "../circuit_builders/circuit_builders.hpp"
19template <
typename Builder>
22 , additive_constant(
bb::
fr::zero())
23 , multiplicative_constant(
bb::
fr::one())
24 , witness_index(IS_CONSTANT)
27template <
typename Builder>
30 , additive_constant(
bb::
fr::zero())
31 , multiplicative_constant(
bb::
fr::one())
32 , witness_index(
value.witness_index)
37template <
typename Builder>
40 , additive_constant(
value)
41 , multiplicative_constant(
bb::
fr::one())
42 , witness_index(IS_CONSTANT)
45template <
typename Builder>
61template <
typename Builder>
89 const bool add_constant_check = (additive_constant ==
bb::fr::zero());
90 const bool mul_constant_check = (multiplicative_constant ==
bb::fr::one());
92 bool result_inverted =
false;
100 uint32_t witness_idx = witness_index;
101 if ((add_constant_check && mul_constant_check) || inverted_check) {
102 result_inverted = inverted_check;
111 "Attempting to create a bool_t from a witness_t not satisfying x^2 - x = 0");
115 context->create_bool_gate(witness_idx);
131 if (witness_indices_match(*
this, other) && !is_constant()) {
140 }
else if (!is_constant() && other.
is_constant()) {
145 }
else if (is_constant() && !other.
is_constant()) {
155 bb::fr left = ctx->get_variable(witness_index);
157 bb::fr result_value = left * multiplicative_constant;
159 result_value += additive_constant;
163 ctx->create_add_gate({ .a = witness_index,
166 .a_scaling = multiplicative_constant,
203 }
else if (!is_constant() && other.
is_constant()) {
224 }
else if (is_constant() && !other.
is_constant()) {
266 result_value = left * right;
278 ctx->create_arithmetic_gate({ .a = witness_index,
306 return divide_no_zero_check(other);
334 }
else if (!is_constant() && other.
is_constant()) {
346 }
else if (is_constant() && !other.
is_constant()) {
349 if (get_value() == 0) {
354 bb::fr numerator = get_value();
356 denominator_inv = denominator_inv.
is_zero() ? 0 : denominator_inv.
invert();
358 bb::fr out(numerator * denominator_inv);
382 bb::fr numerator = get_value();
384 denominator_inv = denominator_inv.
is_zero() ? 0 : denominator_inv.
invert();
386 bb::fr out(numerator * denominator_inv);
402 bb::fr q_o = -multiplicative_constant;
425 return field_t(get_value().pow(exponent));
431 bool accumulator_initialized =
false;
434 auto shifted_exponent = exponent;
437 while (shifted_exponent != 0) {
438 if (shifted_exponent & 1) {
439 if (!accumulator_initialized) {
440 accumulator = running_power;
441 accumulator_initialized =
true;
443 accumulator *= running_power;
446 if (shifted_exponent >= 2) {
448 running_power = running_power.
sqr();
450 shifted_exponent >>= 1;
465 return field_t(get_value().pow(exponent_value));
469 return pow(
static_cast<uint32_t
>(exponent_value));
476 for (
size_t i = 0; i < exponent_bits.size(); ++i) {
477 uint256_t value_bit = exponent_value & 1;
481 exponent_bits[31 - i] = bit;
482 exponent_value >>= 1;
486 for (
const auto& bit : exponent_bits) {
487 exponent_accumulator += exponent_accumulator;
488 exponent_accumulator += bit;
491 exponent.
assert_equal(exponent_accumulator,
"field_t::pow exponent accumulator incorrect");
496 for (
size_t i = 0; i < 32; ++i) {
497 accumulator *= accumulator;
499 const field_t multiplier = conditional_assign_internal(exponent_bits[i], *
this, one);
500 accumulator *= multiplier;
514 const bool mul_by_const = is_constant() || to_mul.
is_constant();
519 return ((*
this) * to_mul + to_add);
552 bb::fr out =
a *
b * mul_scaling +
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
556 ctx->create_big_mul_add_gate({
557 .a = is_constant() ? ctx->zero_idx() : witness_index,
561 .mul_scaling = mul_scaling,
562 .a_scaling = a_scaling,
563 .b_scaling = b_scaling,
564 .c_scaling = c_scaling,
566 .const_scaling = const_scaling,
579 if (has_const_summand) {
581 return (*
this) + add_b + add_c;
599 bb::fr a_scaling = multiplicative_constant;
609 bb::fr out =
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
615 ctx->create_big_mul_add_gate({
616 .a = is_constant() ? ctx->zero_idx() : witness_index,
621 .a_scaling = a_scaling,
622 .b_scaling = b_scaling,
623 .c_scaling = c_scaling,
625 .const_scaling = const_scaling,
640 if (is_normalized()) {
665 context->create_add_gate({ .a = witness_index,
668 .a_scaling = multiplicative_constant,
671 .const_scaling = additive_constant });
695 context->create_arithmetic_gate({
700 .q_l = multiplicative_constant,
703 .q_c = additive_constant,
737 context->create_arithmetic_gate({
741 .q_m = multiplicative_constant,
743 .q_r = additive_constant,
777 bb::fr native_value = get_value();
778 const bool is_zero_raw = native_value.
is_zero();
830 if (!is_constant()) {
832 return (multiplicative_constant *
context->get_variable(witness_index)) + additive_constant;
836 return additive_constant;
844 return ((*
this) - other).is_zero();
852 return !operator==(other);
858template <
typename Builder>
869 static constexpr bb::fr minus_two(-2);
870 return field_t(predicate).
madd(*
this * minus_two, *
this);
884template <
typename Builder>
901 return (lhs - rhs).
madd(predicate, rhs);
908template <
typename Builder>
912 assert_is_zero(
"0-bit range_constraint on non-zero field_t.");
917 context->decompose_into_default_range(
957 .c = ctx->zero_idx(),
978 const field_t diff = lhs - rhs;
984template <
typename Builder>
988 field_t product = (input - set[0]);
989 for (
size_t i = 1; i < set.size(); i++) {
990 product *= (input - set[i]);
1002template <
typename Builder>
1013 table[3] = T3.
add_two(-table[2], -T1);
1020template <
typename Builder>
1035 table[4] = T3.
add_two(-table[2], -T1);
1036 table[5] = T5.
add_two(-table[3], -T1);
1037 table[6] = T6.
add_two(-table[3], -T2);
1038 table[7] = T7.
add_two(-T6 - T5, T4 - table[4]);
1046template <
typename Builder>
1068template <
typename Builder>
1087template <
typename Builder>
1098 const bool identity_holds = (
a.get_value() +
b.get_value() + c.
get_value() + d.
get_value()).is_zero();
1099 if (!identity_holds && !ctx->failed()) {
1106 ctx->create_big_add_gate({
1107 .a =
a.is_constant() ? ctx->zero_idx() :
a.witness_index,
1108 .b =
b.is_constant() ? ctx->zero_idx() :
b.witness_index,
1111 .a_scaling =
a.multiplicative_constant,
1112 .b_scaling =
b.multiplicative_constant,
1115 .const_scaling = const_scaling,
1123template <
typename Builder>
1134 const bool identity_holds = ((
a.get_value() *
b.get_value()) + c.
get_value() + d.
get_value()).is_zero();
1135 if (!identity_holds && !ctx->failed()) {
1140 bb::fr mul_scaling =
a.multiplicative_constant *
b.multiplicative_constant;
1141 bb::fr a_scaling =
a.multiplicative_constant *
b.additive_constant;
1142 bb::fr b_scaling =
b.multiplicative_constant *
a.additive_constant;
1147 ctx->create_big_mul_add_gate({
1148 .a =
a.is_constant() ? ctx->zero_idx() :
a.witness_index,
1149 .b =
b.is_constant() ? ctx->zero_idx() :
b.witness_index,
1152 .mul_scaling = mul_scaling,
1153 .a_scaling = a_scaling,
1154 .b_scaling = b_scaling,
1155 .c_scaling = c_scaling,
1156 .d_scaling = d_scaling,
1157 .const_scaling = const_scaling,
1169 if (input.empty()) {
1173 if (input.size() == 1) {
1174 return input[0].normalize();
1181 for (
const auto&
element : input) {
1185 accumulator.emplace_back(
element);
1188 if (accumulator.empty()) {
1189 return constant_term;
1193 accumulator[0] += constant_term;
1196 Builder* ctx = validate_context<Builder>(accumulator);
1199 size_t num_elements = accumulator.size();
1201 for (
const auto& acc : accumulator) {
1202 output += acc.get_value();
1206 const size_t num_padding_wires = (num_elements % 3) == 0 ? 0 : 3 - (num_elements % 3);
1207 for (
size_t i = 0; i < num_padding_wires; ++i) {
1210 num_elements = accumulator.size();
1211 const size_t num_gates = (num_elements / 3);
1213 const size_t last_gate_idx = num_gates - 1;
1216 field_t accumulating_total = total;
1229 for (
size_t i = 0; i < last_gate_idx; ++i) {
1240 ctx->create_big_add_gate(
1242 .a = accumulator[3 * i].witness_index,
1243 .b = accumulator[3 * i + 1].witness_index,
1244 .c = accumulator[3 * i + 2].witness_index,
1246 .a_scaling = accumulator[3 * i].multiplicative_constant,
1247 .b_scaling = accumulator[3 * i + 1].multiplicative_constant,
1248 .c_scaling = accumulator[3 * i + 2].multiplicative_constant,
1250 .const_scaling = accumulator[3 * i].additive_constant + accumulator[3 * i + 1].additive_constant +
1251 accumulator[3 * i + 2].additive_constant,
1254 bb::fr new_total = accumulating_total.
get_value() - accumulator[3 * i].get_value() -
1255 accumulator[3 * i + 1].get_value() - accumulator[3 * i + 2].get_value();
1261 ctx->create_big_add_gate({
1262 .a = accumulator[3 * last_gate_idx].witness_index,
1263 .b = accumulator[3 * last_gate_idx + 1].witness_index,
1264 .c = accumulator[3 * last_gate_idx + 2].witness_index,
1266 .a_scaling = accumulator[3 * last_gate_idx].multiplicative_constant,
1267 .b_scaling = accumulator[3 * last_gate_idx + 1].multiplicative_constant,
1268 .c_scaling = accumulator[3 * last_gate_idx + 2].multiplicative_constant,
1270 .const_scaling = accumulator[3 * last_gate_idx].additive_constant +
1271 accumulator[3 * last_gate_idx + 1].additive_constant +
1272 accumulator[3 * last_gate_idx + 2].additive_constant,
1275 for (
const auto& single_input : input) {
1276 new_tag =
OriginTag(new_tag, single_input.tag);
1278 total.
tag = new_tag;
1290template <
typename Builder>
1292 const size_t num_bits)
const
1301 if (is_constant()) {
1308 if (lsb_index == 0) {
1311 create_range_constraint(num_bits,
"split_at: hi value too large.");
1329 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 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()