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);
390 bb::fr numerator = get_value();
392 denominator_inv = denominator_inv.
is_zero() ? 0 : denominator_inv.
invert();
394 bb::fr out(numerator * denominator_inv);
411 bb::fr q_c = -additive_constant;
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;
473 return field_t(get_value().pow(exponent_value));
477 return pow(
static_cast<uint32_t
>(exponent_value));
484 for (
size_t i = 0; i < exponent_bits.size(); ++i) {
485 uint256_t value_bit = exponent_value & 1;
489 exponent_bits[31 - i] = bit;
490 exponent_value >>= 1;
494 for (
const auto& bit : exponent_bits) {
495 exponent_accumulator += exponent_accumulator;
496 exponent_accumulator += bit;
499 exponent.
assert_equal(exponent_accumulator,
"field_t::pow exponent accumulator incorrect");
504 for (
size_t i = 0; i < 32; ++i) {
505 accumulator *= accumulator;
507 const field_t multiplier = conditional_assign_internal(exponent_bits[i], *
this, one);
508 accumulator *= multiplier;
522 const bool mul_by_const = is_constant() || to_mul.
is_constant();
527 return ((*
this) * to_mul + to_add);
560 bb::fr out =
a *
b * mul_scaling +
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
564 ctx->create_big_mul_add_gate({
565 .a = is_constant() ? ctx->zero_idx() : witness_index,
569 .mul_scaling = mul_scaling,
570 .a_scaling = a_scaling,
571 .b_scaling = b_scaling,
572 .c_scaling = c_scaling,
574 .const_scaling = const_scaling,
587 if (has_const_summand) {
589 return (*
this) + add_b + add_c;
607 bb::fr a_scaling = multiplicative_constant;
617 bb::fr out =
a * a_scaling +
b * b_scaling + c * c_scaling + const_scaling;
623 ctx->create_big_mul_add_gate({
624 .a = is_constant() ? ctx->zero_idx() : witness_index,
629 .a_scaling = a_scaling,
630 .b_scaling = b_scaling,
631 .c_scaling = c_scaling,
633 .const_scaling = const_scaling,
648 if (is_normalized()) {
673 context->create_add_gate({ .a = witness_index,
676 .a_scaling = multiplicative_constant,
679 .const_scaling = additive_constant });
703 context->create_arithmetic_gate({
708 .q_l = multiplicative_constant,
711 .q_c = additive_constant,
745 context->create_arithmetic_gate({
749 .q_m = multiplicative_constant,
751 .q_r = additive_constant,
785 bb::fr native_value = get_value();
786 const bool is_zero_raw = native_value.
is_zero();
838 if (!is_constant()) {
840 return (multiplicative_constant *
context->get_variable(witness_index)) + additive_constant;
844 return additive_constant;
852 return ((*
this) - other).is_zero();
860 return !operator==(other);
866template <
typename Builder>
877 static constexpr bb::fr minus_two(-2);
878 return field_t(predicate).
madd(*
this * minus_two, *
this);
892template <
typename Builder>
904 if (witness_indices_match(lhs, rhs) && (lhs.
additive_constant == rhs.additive_constant) &&
911 return (lhs - rhs).
madd(predicate, rhs);
918template <
typename Builder>
922 assert_is_zero(
"0-bit range_constraint on non-zero field_t.");
927 context->create_limbed_range_constraint(
949 ctx->assert_equal_constant(rhs.get_witness_index(), lhs.
get_value(), msg);
950 }
else if (rhs.is_constant()) {
956 const auto rhs_original_tag = rhs.get_origin_tag();
959 rhs.set_origin_tag(empty_tag);
967 .b = rhs.witness_index,
968 .c = ctx->zero_idx(),
970 .b_scaling = -rhs.multiplicative_constant,
973 if ((lhs.
get_value() != rhs.get_value()) && !ctx->failed()) {
980 rhs.set_origin_tag(rhs_original_tag);
989 const field_t diff = lhs - rhs;
995template <
typename Builder>
999 field_t product = (input - set[0]);
1000 for (
size_t i = 1; i < set.size(); i++) {
1001 product *= (input - set[i]);
1013template <
typename Builder>
1024 table[3] = T3.
add_two(-table[2], -T1);
1031template <
typename Builder>
1046 table[4] = T3.
add_two(-table[2], -T1);
1047 table[5] = T5.
add_two(-table[3], -T1);
1048 table[6] = T6.
add_two(-table[3], -T2);
1049 table[7] = T7.
add_two(-T6 - T5, T4 - table[4]);
1057template <
typename Builder>
1079template <
typename Builder>
1098template <
typename Builder>
1109 const bool identity_holds = (
a.get_value() +
b.get_value() + c.
get_value() + d.
get_value()).is_zero();
1110 if (!identity_holds && !ctx->failed()) {
1117 ctx->create_big_add_gate({
1118 .a =
a.is_constant() ? ctx->zero_idx() :
a.witness_index,
1119 .b =
b.is_constant() ? ctx->zero_idx() :
b.witness_index,
1122 .a_scaling =
a.multiplicative_constant,
1123 .b_scaling =
b.multiplicative_constant,
1126 .const_scaling = const_scaling,
1134template <
typename Builder>
1145 const bool identity_holds = ((
a.get_value() *
b.get_value()) + c.
get_value() + d.
get_value()).is_zero();
1146 if (!identity_holds && !ctx->failed()) {
1151 bb::fr mul_scaling =
a.multiplicative_constant *
b.multiplicative_constant;
1152 bb::fr a_scaling =
a.multiplicative_constant *
b.additive_constant;
1153 bb::fr b_scaling =
b.multiplicative_constant *
a.additive_constant;
1158 ctx->create_big_mul_add_gate({
1159 .a =
a.is_constant() ? ctx->zero_idx() :
a.witness_index,
1160 .b =
b.is_constant() ? ctx->zero_idx() :
b.witness_index,
1163 .mul_scaling = mul_scaling,
1164 .a_scaling = a_scaling,
1165 .b_scaling = b_scaling,
1166 .c_scaling = c_scaling,
1167 .d_scaling = d_scaling,
1168 .const_scaling = const_scaling,
1180 if (input.empty()) {
1184 if (input.size() == 1) {
1185 return input[0].normalize();
1192 for (
const auto&
element : input) {
1196 accumulator.emplace_back(
element);
1199 if (accumulator.empty()) {
1200 return constant_term;
1204 accumulator[0] += constant_term;
1207 Builder* ctx = validate_context<Builder>(accumulator);
1210 size_t num_elements = accumulator.size();
1212 for (
const auto& acc : accumulator) {
1213 output += acc.get_value();
1217 const size_t num_padding_wires = (num_elements % 3) == 0 ? 0 : 3 - (num_elements % 3);
1218 for (
size_t i = 0; i < num_padding_wires; ++i) {
1221 num_elements = accumulator.size();
1222 const size_t num_gates = (num_elements / 3);
1224 const size_t last_gate_idx = num_gates - 1;
1227 field_t accumulating_total = total;
1240 for (
size_t i = 0; i < last_gate_idx; ++i) {
1251 ctx->create_big_add_gate(
1253 .a = accumulator[3 * i].witness_index,
1254 .b = accumulator[3 * i + 1].witness_index,
1255 .c = accumulator[3 * i + 2].witness_index,
1257 .a_scaling = accumulator[3 * i].multiplicative_constant,
1258 .b_scaling = accumulator[3 * i + 1].multiplicative_constant,
1259 .c_scaling = accumulator[3 * i + 2].multiplicative_constant,
1261 .const_scaling = accumulator[3 * i].additive_constant + accumulator[3 * i + 1].additive_constant +
1262 accumulator[3 * i + 2].additive_constant,
1265 bb::fr new_total = accumulating_total.
get_value() - accumulator[3 * i].get_value() -
1266 accumulator[3 * i + 1].get_value() - accumulator[3 * i + 2].get_value();
1272 ctx->create_big_add_gate({
1273 .a = accumulator[3 * last_gate_idx].witness_index,
1274 .b = accumulator[3 * last_gate_idx + 1].witness_index,
1275 .c = accumulator[3 * last_gate_idx + 2].witness_index,
1277 .a_scaling = accumulator[3 * last_gate_idx].multiplicative_constant,
1278 .b_scaling = accumulator[3 * last_gate_idx + 1].multiplicative_constant,
1279 .c_scaling = accumulator[3 * last_gate_idx + 2].multiplicative_constant,
1281 .const_scaling = accumulator[3 * last_gate_idx].additive_constant +
1282 accumulator[3 * last_gate_idx + 1].additive_constant +
1283 accumulator[3 * last_gate_idx + 2].additive_constant,
1286 for (
const auto& single_input : input) {
1287 new_tag =
OriginTag(new_tag, single_input.tag);
1289 total.
tag = new_tag;
1301template <
typename Builder>
1303 const size_t num_bits)
const
1312 if (is_constant()) {
1319 if (lsb_index == 0) {
1322 create_range_constraint(num_bits,
"split_at: hi value too large.");
1340 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()