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)
28template <
typename Builder>
31 , additive_constant(
bb::
fr::zero())
32 , multiplicative_constant(
bb::
fr::one())
33 , witness_index(
value.witness_index)
38template <
typename Builder>
41 , additive_constant(
value)
42 , multiplicative_constant(
bb::
fr::one())
43 , witness_index(IS_CONSTANT)
46template <
typename Builder>
62template <
typename Builder>
84 "Attempting to create a bool_t from a witness_t not satisfying x^2 - x = 0");
91 const bool add_constant_check = (additive_constant ==
bb::fr::zero());
92 const bool mul_constant_check = (multiplicative_constant ==
bb::fr::one());
94 bool result_inverted =
false;
102 uint32_t witness_idx = witness_index;
103 if ((add_constant_check && mul_constant_check) || inverted_check) {
104 result_inverted = inverted_check;
112 "Attempting to create a bool_t from a witness_t not satisfying x^2 - x = 0");
116 context->create_bool_gate(witness_idx);
132 if (witness_indices_match(*
this, other) && !is_constant()) {
141 }
else if (!is_constant() && other.
is_constant()) {
146 }
else if (is_constant() && !other.
is_constant()) {
156 bb::fr left = ctx->get_variable(witness_index);
158 bb::fr result_value = left * multiplicative_constant;
160 result_value += additive_constant;
164 ctx->create_add_gate({ .a = witness_index,
167 .a_scaling = multiplicative_constant,
204 }
else if (!is_constant() && other.
is_constant()) {
225 }
else if (is_constant() && !other.
is_constant()) {
267 result_value = left * right;
279 ctx->create_arithmetic_gate({ .a = witness_index,
307 return divide_no_zero_check(other);
335 }
else if (!is_constant() && other.
is_constant()) {
347 }
else if (is_constant() && !other.
is_constant()) {
350 if (get_value() == 0) {
355 bb::fr numerator = get_value();
357 denominator_inv = denominator_inv.
is_zero() ? 0 : denominator_inv.
invert();
359 bb::fr out(numerator * denominator_inv);
383 bb::fr numerator = get_value();
385 denominator_inv = denominator_inv.
is_zero() ? 0 : denominator_inv.
invert();
387 bb::fr out(numerator * denominator_inv);
403 bb::fr q_o = -multiplicative_constant;
426 return field_t(get_value().pow(exponent));
432 bool accumulator_initialized =
false;
435 auto shifted_exponent = exponent;
438 while (shifted_exponent != 0) {
439 if (shifted_exponent & 1) {
440 if (!accumulator_initialized) {
441 accumulator = running_power;
442 accumulator_initialized =
true;
444 accumulator *= running_power;
447 if (shifted_exponent >= 2) {
449 running_power = running_power.
sqr();
451 shifted_exponent >>= 1;
466 return field_t(get_value().pow(exponent_value));
470 return pow(
static_cast<uint32_t
>(exponent_value));
477 for (
size_t i = 0; i < exponent_bits.size(); ++i) {
478 uint256_t value_bit = exponent_value & 1;
482 exponent_bits[31 - i] = bit;
483 exponent_value >>= 1;
487 for (
const auto& bit : exponent_bits) {
488 exponent_accumulator += exponent_accumulator;
489 exponent_accumulator += bit;
492 exponent.
assert_equal(exponent_accumulator,
"field_t::pow exponent accumulator incorrect");
497 for (
size_t i = 0; i < 32; ++i) {
498 accumulator *= accumulator;
500 const field_t multiplier = conditional_assign_internal(exponent_bits[i], *
this, one);
501 accumulator *= multiplier;
515 const bool mul_by_const = is_constant() || to_mul.
is_constant();
520 return ((*
this) * to_mul + to_add);
553 bb::fr out =
a *
b * mul_scaling +
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
557 ctx->create_big_mul_add_gate({
558 .a = is_constant() ? ctx->zero_idx() : witness_index,
562 .mul_scaling = mul_scaling,
563 .a_scaling = a_scaling,
564 .b_scaling = b_scaling,
565 .c_scaling = c_scaling,
567 .const_scaling = const_scaling,
580 if (has_const_summand) {
582 return (*
this) + add_b + add_c;
600 bb::fr a_scaling = multiplicative_constant;
610 bb::fr out =
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
616 ctx->create_big_mul_add_gate({
617 .a = is_constant() ? ctx->zero_idx() : witness_index,
622 .a_scaling = a_scaling,
623 .b_scaling = b_scaling,
624 .c_scaling = c_scaling,
626 .const_scaling = const_scaling,
641 if (is_normalized()) {
666 context->create_add_gate({ .a = witness_index,
669 .a_scaling = multiplicative_constant,
672 .const_scaling = additive_constant });
696 context->create_arithmetic_gate({
701 .q_l = multiplicative_constant,
704 .q_c = additive_constant,
738 context->create_arithmetic_gate({
742 .q_m = multiplicative_constant,
744 .q_r = additive_constant,
778 bb::fr native_value = get_value();
779 const bool is_zero_raw = native_value.
is_zero();
831 if (!is_constant()) {
833 return (multiplicative_constant *
context->get_variable(witness_index)) + additive_constant;
837 return additive_constant;
845 return ((*
this) - other).is_zero();
853 return !operator==(other);
859template <
typename Builder>
870 static constexpr bb::fr minus_two(-2);
871 return field_t(predicate).
madd(*
this * minus_two, *
this);
885template <
typename Builder>
902 return (lhs - rhs).
madd(predicate, rhs);
909template <
typename Builder>
913 assert_is_zero(
"0-bit range_constraint on non-zero field_t.");
918 context->create_limbed_range_constraint(
958 .c = ctx->zero_idx(),
979 const field_t diff = lhs - rhs;
985template <
typename Builder>
989 field_t product = (input - set[0]);
990 for (
size_t i = 1; i < set.size(); i++) {
991 product *= (input - set[i]);
1003template <
typename Builder>
1014 table[3] = T3.
add_two(-table[2], -T1);
1021template <
typename Builder>
1036 table[4] = T3.
add_two(-table[2], -T1);
1037 table[5] = T5.
add_two(-table[3], -T1);
1038 table[6] = T6.
add_two(-table[3], -T2);
1039 table[7] = T7.
add_two(-T6 - T5, T4 - table[4]);
1047template <
typename Builder>
1069template <
typename Builder>
1088template <
typename Builder>
1099 const bool identity_holds = (
a.get_value() +
b.get_value() + c.
get_value() + d.
get_value()).is_zero();
1100 if (!identity_holds && !ctx->failed()) {
1107 ctx->create_big_add_gate({
1108 .a =
a.is_constant() ? ctx->zero_idx() :
a.witness_index,
1109 .b =
b.is_constant() ? ctx->zero_idx() :
b.witness_index,
1112 .a_scaling =
a.multiplicative_constant,
1113 .b_scaling =
b.multiplicative_constant,
1116 .const_scaling = const_scaling,
1124template <
typename Builder>
1135 const bool identity_holds = ((
a.get_value() *
b.get_value()) + c.
get_value() + d.
get_value()).is_zero();
1136 if (!identity_holds && !ctx->failed()) {
1141 bb::fr mul_scaling =
a.multiplicative_constant *
b.multiplicative_constant;
1142 bb::fr a_scaling =
a.multiplicative_constant *
b.additive_constant;
1143 bb::fr b_scaling =
b.multiplicative_constant *
a.additive_constant;
1148 ctx->create_big_mul_add_gate({
1149 .a =
a.is_constant() ? ctx->zero_idx() :
a.witness_index,
1150 .b =
b.is_constant() ? ctx->zero_idx() :
b.witness_index,
1153 .mul_scaling = mul_scaling,
1154 .a_scaling = a_scaling,
1155 .b_scaling = b_scaling,
1156 .c_scaling = c_scaling,
1157 .d_scaling = d_scaling,
1158 .const_scaling = const_scaling,
1170 if (input.empty()) {
1174 if (input.size() == 1) {
1175 return input[0].normalize();
1182 for (
const auto&
element : input) {
1186 accumulator.emplace_back(
element);
1189 if (accumulator.empty()) {
1190 return constant_term;
1194 accumulator[0] += constant_term;
1197 Builder* ctx = validate_context<Builder>(accumulator);
1200 size_t num_elements = accumulator.size();
1202 for (
const auto& acc : accumulator) {
1203 output += acc.get_value();
1207 const size_t num_padding_wires = (num_elements % 3) == 0 ? 0 : 3 - (num_elements % 3);
1208 for (
size_t i = 0; i < num_padding_wires; ++i) {
1211 num_elements = accumulator.size();
1212 const size_t num_gates = (num_elements / 3);
1214 const size_t last_gate_idx = num_gates - 1;
1217 field_t accumulating_total = total;
1230 for (
size_t i = 0; i < last_gate_idx; ++i) {
1241 ctx->create_big_add_gate(
1243 .a = accumulator[3 * i].witness_index,
1244 .b = accumulator[3 * i + 1].witness_index,
1245 .c = accumulator[3 * i + 2].witness_index,
1247 .a_scaling = accumulator[3 * i].multiplicative_constant,
1248 .b_scaling = accumulator[3 * i + 1].multiplicative_constant,
1249 .c_scaling = accumulator[3 * i + 2].multiplicative_constant,
1251 .const_scaling = accumulator[3 * i].additive_constant + accumulator[3 * i + 1].additive_constant +
1252 accumulator[3 * i + 2].additive_constant,
1255 bb::fr new_total = accumulating_total.
get_value() - accumulator[3 * i].get_value() -
1256 accumulator[3 * i + 1].get_value() - accumulator[3 * i + 2].get_value();
1262 ctx->create_big_add_gate({
1263 .a = accumulator[3 * last_gate_idx].witness_index,
1264 .b = accumulator[3 * last_gate_idx + 1].witness_index,
1265 .c = accumulator[3 * last_gate_idx + 2].witness_index,
1267 .a_scaling = accumulator[3 * last_gate_idx].multiplicative_constant,
1268 .b_scaling = accumulator[3 * last_gate_idx + 1].multiplicative_constant,
1269 .c_scaling = accumulator[3 * last_gate_idx + 2].multiplicative_constant,
1271 .const_scaling = accumulator[3 * last_gate_idx].additive_constant +
1272 accumulator[3 * last_gate_idx + 1].additive_constant +
1273 accumulator[3 * last_gate_idx + 2].additive_constant,
1276 for (
const auto& single_input : input) {
1277 new_tag =
OriginTag(new_tag, single_input.tag);
1279 total.
tag = new_tag;
1291template <
typename Builder>
1293 const size_t num_bits)
const
1302 if (is_constant()) {
1309 if (lsb_index == 0) {
1312 create_range_constraint(num_bits,
"split_at: hi value too large.");
1330 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()