7#include "../field/field.hpp"
8#include "../field/field_utils.hpp"
30 *
this = constant_infinity(_context);
40template <
typename Builder>
71 if (assert_on_curve) {
85template <
typename Builder>
89 , _is_infinity(is_infinity)
91 if (_x.get_context() !=
nullptr) {
93 }
else if (_y.get_context() !=
nullptr) {
100 *
this = constant_infinity(this->
context);
105 if (_x.is_constant() != _y.is_constant()) {
106 if (_x.is_constant()) {
107 _x.convert_constant_to_fixed_witness(
context);
109 _y.convert_constant_to_fixed_witness(
context);
114 BB_ASSERT(!(_x.is_constant() && _y.is_constant() && !_is_infinity.is_constant()),
115 "cycle_group: constant coordinates with non-constant infinity flag");
118 BB_ASSERT(get_value().on_curve(),
"cycle_group: Point is not on curve");
119 if (assert_on_curve) {
133template <
typename Builder>
135 : _x(_in.is_point_at_infinity() ? 0 : _in.x)
136 , _y(_in.is_point_at_infinity() ? 0 : _in.y)
137 , _is_infinity(_in.is_point_at_infinity())
167 if (_context !=
nullptr) {
188template <
typename Builder>
214template <
typename Builder>
220 result = constant_infinity(_context);
235 if (get_context() !=
nullptr) {
236 return get_context();
244 if (is_point_at_infinity().get_value()) {
260 static_assert(Group::curve_a == 0);
263 auto res = _y.madd(_y, -xxx - Group::curve_b);
265 res *= !is_point_at_infinity();
266 res.assert_is_zero();
297template <
typename Builder>
301 if (this->is_constant_point_at_infinity()) {
312 if (hint.has_value()) {
316 const bb::fr x1 = _x.get_value();
317 const bb::fr y1 = modified_y.get_value();
323 const bb::fr x_pow_4 = x1 * (y_pow_2 - Group::curve_b);
324 const bb::fr lambda_squared = (x_pow_4 * 9) / (y_pow_2 * 4);
325 const bb::fr lambda = (x1 * x1 * 3) / (y1 + y1);
326 x3 = lambda_squared - x1 - x1;
327 y3 = lambda * (x1 - x3) - y1;
333 result =
cycle_group(x3, y3, is_point_at_infinity(),
false);
342 .
x1 = _x.get_witness_index(),
343 .y1 = modified_y.get_witness_index(),
368template <
typename Builder>
376 false,
"cycle_group::_unconditional_add_or_subtract called on point at infinity");
378 false,
"cycle_group::_unconditional_add_or_subtract called on point at infinity");
380 auto context = get_context(other);
384 const bool lhs_constant = is_constant();
387 if (lhs_constant && !rhs_constant) {
389 lhs.set_origin_tag(get_origin_tag());
390 return lhs._unconditional_add_or_subtract(other, is_addition, hint);
392 if (!lhs_constant && rhs_constant) {
395 return _unconditional_add_or_subtract(rhs, is_addition, hint);
401 if (hint.has_value()) {
417 if (lhs_constant && rhs_constant) {
425 .
x1 = _x.get_witness_index(),
426 .y1 = _y.get_witness_index(),
431 .is_addition = is_addition,
447template <
typename Builder>
451 return _unconditional_add_or_subtract(other,
true, hint);
460template <
typename Builder>
464 return _unconditional_add_or_subtract(other,
false, hint);
478template <
typename Builder>
482 const field_t x_delta = this->_x - other.
_x;
486 x_delta.
assert_is_not_zero(
"cycle_group::checked_unconditional_add, x-coordinate collision");
488 return unconditional_add(other, hint);
503template <
typename Builder>
507 const field_t x_delta = this->_x - other.
_x;
511 x_delta.
assert_is_not_zero(
"cycle_group::checked_unconditional_subtract, x-coordinate collision");
513 return unconditional_subtract(other, hint);
534 if (this->is_constant_point_at_infinity()) {
541 const bool_t x_coordinates_match = (_x == other.
_x);
542 const bool_t y_coordinates_match = (_y == other.
_y);
555 lambda = (y2 - y1).divide_no_zero_check(x_diff);
565 const field_t add_result_x = lambda.
madd(lambda, -(x2 + x1));
566 const field_t add_result_y = lambda.
madd(x1 - add_result_x, -y1);
572 const bool_t double_predicate = (x_coordinates_match && y_coordinates_match);
577 const bool_t lhs_infinity = is_point_at_infinity();
588 const bool_t infinity_predicate = (x_coordinates_match && !y_coordinates_match);
589 bool_t result_is_infinity = infinity_predicate && (!lhs_infinity && !rhs_infinity);
590 result_is_infinity = result_is_infinity || (lhs_infinity && rhs_infinity);
592 return cycle_group(result_x, result_y, result_is_infinity,
false);
613 if (this->is_constant_point_at_infinity()) {
623 const bool_t x_coordinates_match = (_x == other.
_x);
624 const bool_t y_coordinates_match = (_y == other.
_y);
637 lambda = (-y2 - y1).divide_no_zero_check(x_diff);
646 const field_t sub_result_x = lambda.
madd(lambda, -(x2 + x1));
647 const field_t sub_result_y = lambda.
madd(x1 - sub_result_x, -y1);
655 const bool_t double_predicate = (x_coordinates_match && !y_coordinates_match);
663 const bool_t lhs_infinity = is_point_at_infinity();
674 const bool_t infinity_predicate = (x_coordinates_match && y_coordinates_match);
676 bool_t result_is_infinity = infinity_predicate && (!lhs_infinity && !rhs_infinity);
677 result_is_infinity = result_is_infinity || (lhs_infinity && rhs_infinity);
679 return cycle_group(result_x, result_y, result_is_infinity,
false);
695 result.
_y = (-_y).normalize();
701 *
this = *
this + other;
707 *
this = *
this - other;
731template <
typename Builder>
736 const bool unconditional_add)
738 BB_ASSERT_EQ(!scalars.empty(),
true,
"Empty scalars provided to variable base batch mul!");
739 BB_ASSERT_EQ(scalars.size(), base_points.size(),
"Points/scalars size mismatch in variable base batch mul!");
740 BB_ASSERT_EQ(offset_generators.size(), base_points.size() + 1,
"Too few offset generators provided!");
741 const size_t num_points = scalars.size();
745 for (
auto [scalar, point] :
zip_view(scalars, base_points)) {
760 scalar_slices.reserve(num_points);
761 for (
const auto& scalar : scalars) {
762 scalar_slices.emplace_back(
context, scalar, ROM_TABLE_BITS);
770 std::vector<Element> operation_transcript;
771 Element offset_generator_accumulator = offset_generators[0];
775 for (
size_t i = 0; i < num_points; ++i) {
781 native_straus_tables.emplace_back(
std::move(table));
785 Element accumulator = offset_generators[0];
786 for (
size_t i = 0; i < num_rounds; ++i) {
789 for (
size_t j = 0; j < ROM_TABLE_BITS; ++j) {
790 accumulator = accumulator.
dbl();
791 operation_transcript.push_back(accumulator);
792 offset_generator_accumulator = offset_generator_accumulator.
dbl();
795 for (
size_t j = 0; j < num_points; ++j) {
797 auto slice_value =
static_cast<size_t>(scalar_slices[j].slices_native[num_rounds - i - 1]);
798 const Element point = native_straus_tables[j][slice_value];
799 accumulator += point;
802 operation_transcript.push_back(accumulator);
803 offset_generator_accumulator +=
Element(offset_generators[j + 1]);
809 Element::batch_normalize(&operation_transcript[0], operation_transcript.size());
810 std::vector<AffineElement> operation_hints;
811 operation_hints.reserve(operation_transcript.size());
818 point_tables.reserve(num_points);
819 const size_t hints_per_table = (1ULL << ROM_TABLE_BITS) - 1;
820 for (
size_t i = 0; i < num_points; ++i) {
824 point_tables.push_back(
std::move(table));
828 AffineElement* hint_ptr = &operation_hints[num_points * hints_per_table];
835 field_t coordinate_check_product = 1;
836 for (
size_t i = 0; i < num_rounds; ++i) {
839 for (
size_t j = 0; j < ROM_TABLE_BITS; ++j) {
840 accumulator = accumulator.
dbl(*hint_ptr);
845 for (
size_t j = 0; j < num_points; ++j) {
846 const field_t scalar_slice = scalar_slices[j][num_rounds - i - 1];
848 const cycle_group point = point_tables[j].read(scalar_slice);
849 if (!unconditional_add) {
850 coordinate_check_product *= point.
_x - accumulator.
_x;
859 if (!unconditional_add) {
860 coordinate_check_product.
assert_is_not_zero(
"_variable_base_batch_mul_internal x-coordinate collision");
870 return { accumulator,
AffineElement(offset_generator_accumulator) };
896template <
typename Builder>
900 BB_ASSERT_EQ(scalars.size(), base_points.size(),
"Points/scalars size mismatch in fixed-base batch mul");
909 for (
const auto [point, scalar] :
zip_view(base_points, scalars)) {
911 multitable_ids.push_back(table_id[0]);
912 multitable_ids.push_back(table_id[1]);
913 scalar_limbs.push_back(scalar.lo());
914 scalar_limbs.push_back(scalar.hi());
919 Element offset_generator_accumulator = Group::point_at_infinity;
920 for (
const auto [table_id, scalar] :
zip_view(multitable_ids, scalar_limbs)) {
925 for (
size_t j = 0; j < lookup_data[ColumnIdx::C2].size(); ++j) {
926 const field_t x = lookup_data[ColumnIdx::C2][j];
927 const field_t y = lookup_data[ColumnIdx::C3][j];
931 lookup_points.push_back(
cycle_group(x, y, is_infinity,
false));
934 offset_generator_accumulator += table::get_generator_offset_for_table_id(table_id);
938 std::vector<Element> operation_transcript;
940 Element accumulator = lookup_points[0].get_value();
941 for (
size_t i = 1; i < lookup_points.size(); ++i) {
942 accumulator += (lookup_points[i].get_value());
943 operation_transcript.push_back(accumulator);
949 Element::batch_normalize(&operation_transcript[0], operation_transcript.size());
950 std::vector<AffineElement> operation_hints;
951 operation_hints.reserve(operation_transcript.size());
961 for (
auto& point : lookup_points) {
962 point.set_origin_tag(const_tag);
965 for (
size_t i = 1; i < lookup_points.size(); ++i) {
966 accumulator = accumulator.
unconditional_add(lookup_points[i], operation_hints[i - 1]);
972 return { accumulator, offset_generator_accumulator };
988template <
typename Builder>
993 const size_t table_bits)
995 BB_ASSERT_EQ(!scalars.empty(),
true,
"Empty scalars provided to fixed base plookup batch mul!");
996 BB_ASSERT_EQ(scalars.size(), base_points.size(),
"Points/scalars size mismatch in fixed base plookup batch mul!");
997 BB_ASSERT_EQ(offset_generators.size(), base_points.size() + 1,
"Too few offset generators provided!");
998 const size_t num_points = scalars.size();
1001 for (
const auto& scalar : scalars) {
1009 "table_bits must evenly divide cycle_scalar::LO_BITS. The Straus algorithm splits the scalar "
1010 "into lo/hi limbs and decomposes each separately; if LO_BITS is not a multiple of table_bits, "
1011 "the hi-limb slices start at the wrong bit-offset and the MSM result is incorrect. "
1012 "Valid values for table_bits (given LO_BITS=128) are: 1, 2, 4, 8, 16, 32, 64, 128.");
1018 scalar_slices.reserve(num_points);
1019 for (
const auto& scalar : scalars) {
1020 scalar_slices.emplace_back(
context, scalar, table_bits);
1028 precomputed_tables[i] =
1032 point_tables.reserve(num_points);
1033 for (
size_t i = 0; i < num_points; ++i) {
1041 std::vector<Element> operation_transcript;
1042 Element offset_generator_accumulator = offset_generators[0];
1045 Element accumulator = offset_generators[0];
1046 for (
size_t i = 0; i < num_rounds; ++i) {
1048 for (
size_t j = 0; j < table_bits; ++j) {
1049 accumulator = accumulator.
dbl();
1050 operation_transcript.push_back(accumulator);
1051 offset_generator_accumulator = offset_generator_accumulator.
dbl();
1054 for (
size_t j = 0; j < num_points; ++j) {
1055 auto slice_value =
static_cast<size_t>(scalar_slices[j].slices_native[num_rounds - i - 1]);
1056 const Element point(point_tables[j].get_native_table()[slice_value]);
1057 accumulator += point;
1058 operation_transcript.push_back(accumulator);
1059 offset_generator_accumulator +=
Element(offset_generators[j + 1]);
1065 Element::batch_normalize(operation_transcript.data(), operation_transcript.size());
1066 std::vector<AffineElement> operation_hints;
1067 operation_hints.reserve(operation_transcript.size());
1076 for (
size_t i = 0; i < num_rounds; ++i) {
1078 for (
size_t j = 0; j < table_bits; ++j) {
1079 accumulator = accumulator.
dbl(*hint_ptr);
1083 for (
size_t j = 0; j < num_points; ++j) {
1084 const field_t scalar_slice = scalar_slices[j][num_rounds - i - 1];
1085 const cycle_group point = point_tables[j].read(scalar_slice);
1094 return { accumulator,
AffineElement(offset_generator_accumulator) };
1109template <
typename Builder>
1113 const size_t table_bits)
1115 BB_ASSERT_EQ(scalars.size(), constant_points.size(),
"Points/scalars size mismatch in fixed_batch_mul!");
1117 if (scalars.empty()) {
1123 for (
auto [point, scalar] :
zip_view(constant_points, scalars)) {
1124 result_tag =
OriginTag(result_tag,
OriginTag(point.get_origin_tag(), scalar.get_origin_tag()));
1128 std::vector<AffineElement> plookup_points;
1129 bool has_non_constant_component =
false;
1130 Element constant_acc = Group::point_at_infinity;
1132 for (
const auto [point, scalar] :
zip_view(constant_points, scalars)) {
1134 if (scalar.is_constant()) {
1136 constant_acc += point.get_value() * scalar.get_value();
1138 if (point.get_value().is_point_at_infinity()) {
1140 auto* ctx = scalar.get_context();
1141 ctx->create_limbed_range_constraint(scalar.lo().get_witness_index(),
1144 "fixed_batch_mul: lo range constraint for scalar with constant "
1146 ctx->create_limbed_range_constraint(scalar.hi().get_witness_index(),
1149 "fixed_batch_mul: hi range constraint for scalar with constant "
1153 plookup_scalars.push_back(scalar);
1154 plookup_points.push_back(point.get_value());
1155 has_non_constant_component =
true;
1159 if (!has_non_constant_component) {
1161 result.set_origin_tag(result_tag);
1166 const size_t num_offset_generators = plookup_points.size() + 1;
1168 context.generators->get(num_offset_generators, 0, OFFSET_GENERATOR_DOMAIN_SEPARATOR);
1171 Element offset_accumulator = -constant_acc;
1172 const auto [accumulator, offset_generator_delta] =
1173 _fixed_base_plookup_batch_mul_internal(plookup_scalars, plookup_points, offset_generators, table_bits);
1174 offset_accumulator += offset_generator_delta;
1225template <
typename Builder>
1230 BB_ASSERT_EQ(scalars.size(), base_points.size(),
"Points/scalars size mismatch in batch mul!");
1232 if (scalars.empty()) {
1240 std::vector<AffineElement> fixed_base_points;
1244 for (
auto [point, scalar] :
zip_view(base_points, scalars)) {
1245 result_tag =
OriginTag(result_tag,
OriginTag(point.get_origin_tag(), scalar.get_origin_tag()));
1250 bool can_unconditional_add =
true;
1251 bool has_non_constant_component =
false;
1252 Element constant_acc = Group::point_at_infinity;
1253 for (
const auto [point, scalar] :
zip_view(base_points, scalars)) {
1254 if (scalar.is_constant() && point.is_constant()) {
1256 constant_acc += (point.get_value()) * (scalar.get_value());
1257 }
else if (!scalar.is_constant() && point.is_constant()) {
1258 if (point.get_value().is_point_at_infinity()) {
1260#ifndef FUZZING_DISABLE_WARNINGS
1261 info(
"Warning: Performing batch mul with constant point at infinity!");
1265 auto* ctx = scalar.get_context();
1266 ctx->create_limbed_range_constraint(scalar.lo().get_witness_index(),
1269 "batch_mul: lo range constraint for scalar with constant "
1271 ctx->create_limbed_range_constraint(scalar.hi().get_witness_index(),
1274 "batch_mul: hi range constraint for scalar with constant "
1280 fixed_base_scalars.push_back(scalar);
1281 fixed_base_points.push_back(point.get_value());
1284 variable_base_scalars.push_back(scalar);
1285 variable_base_points.push_back(point);
1287 has_non_constant_component =
true;
1290 variable_base_scalars.push_back(scalar);
1291 variable_base_points.push_back(point);
1292 can_unconditional_add =
false;
1293 has_non_constant_component =
true;
1298 if (!has_non_constant_component) {
1300 result.set_origin_tag(result_tag);
1306 Element offset_accumulator = -constant_acc;
1307 const bool has_variable_points = !variable_base_points.empty();
1308 const bool has_fixed_points = !fixed_base_points.empty();
1311 if (has_fixed_points) {
1313 const auto [fixed_accumulator, offset_generator_delta] =
1314 _fixed_base_batch_mul_internal(fixed_base_scalars, fixed_base_points);
1315 offset_accumulator += offset_generator_delta;
1316 result = fixed_accumulator;
1319 if (has_variable_points) {
1321 const size_t num_offset_generators = variable_base_points.size() + 1;
1323 context.generators->get(num_offset_generators, 0, OFFSET_GENERATOR_DOMAIN_SEPARATOR);
1326 const auto [variable_accumulator, offset_generator_delta] = _variable_base_batch_mul_internal(
1327 variable_base_scalars, variable_base_points, offset_generators, can_unconditional_add);
1328 offset_accumulator += offset_generator_delta;
1331 if (has_fixed_points) {
1335 result = variable_accumulator;
1367 return batch_mul({ *
this }, { scalar });
1378 return batch_mul({ *
this }, { scalar });
1389 this->standardize();
1391 const auto equal = (_x == other.
_x) && (_y == other.
_y) && (this->_is_infinity == other.
_is_infinity);
1397 this->standardize();
1399 _x.assert_equal(other.
_x, msg);
1400 _y.assert_equal(other.
_y, msg);
1404template <
typename Builder>
1411 auto _is_infinity_res =
#define BB_ASSERT(expression,...)
#define BB_ASSERT_EQ(actual, expected,...)
constexpr bool is_point_at_infinity() const noexcept
constexpr void self_set_infinity() noexcept
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
constexpr element dbl() const noexcept
BB_INLINE constexpr bool is_point_at_infinity() const noexcept
Container for lookup accumulator values and table reads.
Generates plookup tables required to perform fixed-base scalar multiplication over a fixed number of ...
static bool lookup_table_exists_for_point(const affine_element &input)
Returns true iff provided point is one of the two for which we have a precomputed lookup table.
Implements boolean logic in-circuit.
static bool_t conditional_assign(const bool_t< Builder > &predicate, const bool_t &lhs, const bool_t &rhs)
Conditionally assign lhs or rhs based on predicate, always returns normalized result.
Builder * get_context() const
void assert_equal(const bool_t &rhs, std::string const &msg="bool_t::assert_equal") const
Implements copy constraint for bool_t elements.
cycle_group represents a group Element of the proving system's embedded curve, i.e....
cycle_group dbl(const std::optional< AffineElement > hint=std::nullopt) const
Evaluates a point doubling using Ultra ECC double gate (if non-constant)
static cycle_group from_constant_witness(Builder *_context, const AffineElement &_in)
Converts a native AffineElement into a witness, but constrains the witness values to be known constan...
cycle_group & operator*=(const cycle_scalar &scalar)
void standardize()
Convert the point to standard form.
cycle_group unconditional_add(const cycle_group &other, const std::optional< AffineElement > hint=std::nullopt) const
Evaluate incomplete ECC point addition over *this and other.
void validate_on_curve() const
On-curve check.
bool_t operator==(cycle_group &other)
Builder * get_context(const cycle_group &other) const
cycle_group & operator-=(const cycle_group &other)
static cycle_group conditional_assign(const bool_t &predicate, const cycle_group &lhs, const cycle_group &rhs)
void unset_free_witness_tag()
Unset the free witness flag for the cycle_group's tags.
cycle_group checked_unconditional_subtract(const cycle_group &other, const std::optional< AffineElement > hint=std::nullopt) const
Evaluate incomplete ECC point subtraction over *this and other, with x-coordinate collision checks.
cycle_group _unconditional_add_or_subtract(const cycle_group &other, bool is_addition, const std::optional< AffineElement > hint) const
Will evaluate ECC point addition or subtraction over *this and other.
static cycle_group from_witness(Builder *_context, const AffineElement &_in)
Converts an AffineElement into a circuit witness.
cycle_group operator-() const
Negates a point.
static cycle_group one(Builder *_context)
Construct a constant cycle_group representation of Group::one.
void set_free_witness_tag()
Set the free witness flag for the cycle_group's tags.
void set_origin_tag(OriginTag tag) const
Set the origin tag for x, y and _is_infinity members of cycle_group.
cycle_group & operator+=(const cycle_group &other)
static batch_mul_internal_output _fixed_base_plookup_batch_mul_internal(std::span< cycle_scalar > scalars, std::span< AffineElement const > base_points, std::span< AffineElement const > offset_generators, size_t table_bits=ROM_TABLE_BITS)
Internal algorithm to perform a fixed-base batch mul using plookup tables.
static cycle_group constant_infinity(Builder *_context=nullptr)
Construct a constant point at infinity.
bool is_constant_point_at_infinity() const
static cycle_group fixed_batch_mul(const std::vector< cycle_group > &constant_points, const std::vector< BigScalarField > &scalars, GeneratorContext context={}, size_t table_bits=ROM_TABLE_BITS)
bool_t is_point_at_infinity() const
static batch_mul_internal_output _variable_base_batch_mul_internal(std::span< cycle_scalar > scalars, std::span< cycle_group > base_points, std::span< AffineElement const > offset_generators, bool unconditional_add)
Internal logic to perform a variable-base batch mul using the Straus MSM algorithm.
cycle_group(Builder *_context=nullptr)
Construct a new constant point at infinity cycle group object.
AffineElement get_value() const
OriginTag get_origin_tag() const
Get the origin tag of cycle_group (a merege of origin tags of x, y and _is_infinity members)
cycle_group operator*(const cycle_scalar &scalar) const
static batch_mul_internal_output _fixed_base_batch_mul_internal(std::span< cycle_scalar > scalars, std::span< AffineElement > base_points)
Internal algorithm to perform a fixed-base batch mul.
void assert_equal(cycle_group &other, std::string const &msg="cycle_group::assert_equal")
cycle_group operator+(const cycle_group &other) const
Evaluate ECC point addition over *this and other.
cycle_group unconditional_subtract(const cycle_group &other, const std::optional< AffineElement > hint=std::nullopt) const
Evaluate incomplete ECC point subtraction over *this and other.
Builder * get_context() const
cycle_group checked_unconditional_add(const cycle_group &other, const std::optional< AffineElement > hint=std::nullopt) const
Evaluate incomplete ECC point addition over *this and other, with x-coordinate collision checks.
static cycle_group batch_mul(const std::vector< cycle_group > &base_points, const std::vector< BigScalarField > &scalars, GeneratorContext context={})
Represents a member of the Grumpkin curve scalar field (i.e. BN254 base field).
static constexpr size_t NUM_BITS
static constexpr size_t LO_BITS
static constexpr size_t HI_BITS
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.
field_t madd(const field_t &to_mul, const field_t &to_add) const
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.
Builder * get_context() const
OriginTag get_origin_tag() const
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
static field_t from_witness(Builder *ctx, const bb::fr &input)
bool_t< Builder > is_zero() const
Validate whether a field_t element is zero.
void convert_constant_to_fixed_witness(Builder *ctx)
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.
static field_t conditional_assign(const bool_t< Builder > &predicate, const field_t &lhs, const field_t &rhs)
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.
uint32_t get_witness_index() const
Get the witness index of the current field element.
static plookup::ReadData< field_pt > get_lookup_accumulators(const plookup::MultiTableId id, const field_pt &key_a, const field_pt &key_b=0, const bool is_2_to_1_lookup=false)
straus_lookup_table computes a lookup table of size 1 << table_bits
static std::vector< Element > compute_native_table(const Element &base_point, const Element &offset_generator, size_t table_bits)
Compute the output points generated when computing the Straus lookup table.
static PrecomputedData build_precomputed_data(const AffineElement &base_point, const AffineElement &offset_generator, size_t table_bits)
Compute native table entries and BasicTable column data without touching the circuit builder.
StrictMock< MockContext > context
bb::curve::BN254::Element Element
constexpr T ceil_div(const T &numerator, const T &denominator)
Computes the ceiling of the division of two integral types.
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).
field< Bn254FrParams > fr
Univariate< Fr, domain_end > operator*(const Fr &ff, const Univariate< Fr, domain_end > &uv)
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
This file contains part of the logic for the Origin Tag mechanism that tracks the use of in-circuit p...
static OriginTag constant()
BB_INLINE constexpr field sqr() const noexcept
static constexpr field zero()
Stores temporary variables produced by internal multiplication algorithms.