7#include "../field/field.hpp"
28template <
typename Builder>
45template <
typename Builder>
49 , _is_infinity(is_infinity)
50 , _is_constant(_x.is_constant() && _y.is_constant() && is_infinity.is_constant())
51 , _is_standard(is_infinity.is_constant())
87template <
typename Builder>
89 : x(is_infinity ? 0 : _x)
90 , y(is_infinity ? 0 : _y)
91 , _is_infinity(is_infinity)
96 ASSERT(get_value().on_curve());
109template <
typename Builder>
111 : x(_in.is_point_at_infinity() ? 0 : _in.x)
112 , y(_in.is_point_at_infinity() ? 0 : _in.y)
113 , _is_infinity(_in.is_point_at_infinity())
145template <
typename Builder>
153 if (_in.is_point_at_infinity()) {
180template <
typename Builder>
188 if (_in.is_point_at_infinity()) {
208 if (get_context() !=
nullptr) {
209 return get_context();
217 if (is_point_at_infinity().get_value()) {
218 result.self_set_infinity();
231 static_assert(Group::curve_a == 0);
234 auto res = y.madd(y, -xxx - Group::curve_b);
237 res *= !is_point_at_infinity();
238 res.assert_is_zero();
257 BB_ASSERT_EQ(this->x.is_constant() && this->y.is_constant() && this->_is_infinity.is_constant(),
260 this->_is_standard =
true;
262 if (is_infinity.
is_constant() && this->_is_infinity.is_constant()) {
270 this->_is_infinity =
true;
271 this->_is_constant =
true;
276 if (is_infinity.
is_constant() && !this->_is_infinity.is_constant()) {
280 this->_is_infinity =
true;
281 this->_is_constant =
true;
283 this->_is_infinity.assert_equal(
false);
284 this->_is_infinity =
false;
289 if (this->_is_infinity.is_constant() && this->_is_infinity.get_value()) {
295 this->_is_constant =
true;
303 ASSERT(!this->x.is_constant());
304 ASSERT(!this->y.is_constant());
305 this->_is_constant =
false;
308 bool_t set_allowed = (this->_is_infinity == is_infinity) || is_infinity;
310 this->_is_infinity = is_infinity;
313 if (this->
context ==
nullptr) {
325 BB_ASSERT_EQ(this->x.is_constant() && this->y.is_constant() && this->_is_infinity.is_constant(),
327 if (this->_is_infinity.is_constant() && this->_is_infinity.get_value()) {
328 ASSERT(this->_is_constant);
329 ASSERT(this->_is_standard);
332 if (this->_is_standard) {
335 this->_is_standard =
true;
348template <
typename Builder>
359 if (this->is_point_at_infinity().is_constant() && this->is_point_at_infinity().get_value()) {
364 if (hint.has_value()) {
365 auto x3 = hint.value().
x;
366 auto y3 = hint.value().y;
368 result =
cycle_group(x3, y3, is_point_at_infinity());
377 auto x1 = x.get_value();
378 auto y1 = modified_y.get_value();
384 auto y_pow_2 = y1.sqr();
385 auto x_pow_4 = x1 * (y_pow_2 - Group::curve_b);
386 auto lambda_squared = (x_pow_4 * 9) / (y_pow_2 * 4);
387 auto lambda = (x1 * x1 * 3) / (y1 + y1);
388 auto x3 = lambda_squared - x1 - x1;
389 auto y3 = lambda * (x1 - x3) - y1;
391 auto result =
cycle_group(x3, y3, is_point_at_infinity().get_value());
401 .
x1 = x.get_witness_index(),
402 .y1 = modified_y.get_witness_index(),
425template <
typename Builder>
430 auto context = get_context(other);
432 const bool lhs_constant = is_constant();
433 const bool rhs_constant = other.is_constant();
434 if (lhs_constant && !rhs_constant) {
437 lhs.set_origin_tag(get_origin_tag());
438 return lhs.unconditional_add(other, hint);
440 if (!lhs_constant && rhs_constant) {
443 rhs.set_origin_tag(other.get_origin_tag());
444 return unconditional_add(rhs, hint);
447 if (hint.has_value()) {
448 auto x3 = hint.value().
x;
449 auto y3 = hint.value().y;
450 if (lhs_constant && rhs_constant) {
455 const auto p1 = get_value();
456 const auto p2 = other.get_value();
458 if (lhs_constant && rhs_constant) {
469 .
x1 = x.get_witness_index(),
470 .y1 = y.get_witness_index(),
471 .x2 = other.x.get_witness_index(),
472 .y2 = other.y.get_witness_index(),
475 .sign_coefficient = 1,
477 context->create_ecc_add_gate(add_gate);
495template <
typename Builder>
499 if constexpr (!IS_ULTRA) {
500 return unconditional_add(-other, hint);
502 auto context = get_context(other);
504 const bool lhs_constant = is_constant();
507 if (lhs_constant && !rhs_constant) {
510 lhs.set_origin_tag(get_origin_tag());
511 return lhs.unconditional_subtract(other, hint);
513 if (!lhs_constant && rhs_constant) {
517 return unconditional_subtract(rhs);
520 if (hint.has_value()) {
521 auto x3 = hint.value().
x;
522 auto y3 = hint.value().y;
523 if (lhs_constant && rhs_constant) {
528 auto p1 = get_value();
531 if (lhs_constant && rhs_constant) {
542 .
x1 = x.get_witness_index(),
543 .y1 = y.get_witness_index(),
548 .sign_coefficient = -1,
550 context->create_ecc_add_gate(add_gate);
571template <
typename Builder>
575 field_t x_delta = this->x - other.
x;
579 x_delta.
assert_is_not_zero(
"cycle_group::checked_unconditional_add, x-coordinate collision");
581 return unconditional_add(other, hint);
597template <
typename Builder>
601 field_t x_delta = this->x - other.
x;
605 x_delta.
assert_is_not_zero(
"cycle_group::checked_unconditional_subtract, x-coordinate collision");
607 return unconditional_subtract(other, hint);
622 if (this->_is_infinity.is_constant() && this->_is_infinity.get_value()) {
629 const bool_t x_coordinates_match = (x == other.
x);
630 const bool_t y_coordinates_match = (y == other.
y);
631 const bool_t double_predicate = (x_coordinates_match && y_coordinates_match);
632 const bool_t infinity_predicate = (x_coordinates_match && !y_coordinates_match);
640 auto x_diff = x2.
add_two(-x1, x_coordinates_match);
643 if ((y1.is_constant() && y2.is_constant()) || x_diff.is_constant()) {
644 lambda = (y2 - y1).divide_no_zero_check(x_diff);
647 field_t::from_witness(this->get_context(other), (y2.get_value() - y1.get_value()) / x_diff.get_value());
653 auto x3 = lambda.
madd(lambda, -(x2 + x1));
654 auto y3 = lambda.
madd(x1 - x3, -y1);
655 cycle_group add_result(x3, y3, x_coordinates_match);
657 auto dbl_result = dbl();
664 const bool_t lhs_infinity = is_point_at_infinity();
677 bool_t result_is_infinity = infinity_predicate && (!lhs_infinity && !rhs_infinity);
678 result_is_infinity = result_is_infinity || (lhs_infinity && rhs_infinity);
680 return cycle_group(result_x, result_y, result_is_infinity);
698 if (this->_is_infinity.is_constant() && this->_is_infinity.get_value()) {
702 const bool_t x_coordinates_match = (x == other.
x);
703 const bool_t y_coordinates_match = (y == other.
y);
704 const bool_t double_predicate = (x_coordinates_match && !y_coordinates_match).normalize();
705 const bool_t infinity_predicate = (x_coordinates_match && y_coordinates_match).normalize();
715 auto x_diff = x2.
add_two(-x1, x_coordinates_match);
718 if ((y1.is_constant() && y2.is_constant()) || x_diff.is_constant()) {
719 lambda = (-y2 - y1).divide_no_zero_check(x_diff);
722 field_t::from_witness(this->get_context(other), (-y2.get_value() - y1.get_value()) / x_diff.get_value());
728 auto x3 = lambda.
madd(lambda, -(x2 + x1));
729 auto y3 = lambda.
madd(x1 - x3, -y1);
730 cycle_group add_result(x3, y3, x_coordinates_match);
732 auto dbl_result = dbl();
740 if (result_x.get_context()) {
741 result_x.get_context()->update_used_witnesses(result_x.witness_index);
743 if (result_y.get_context()) {
744 result_y.get_context()->update_used_witnesses(result_y.witness_index);
748 const bool_t lhs_infinity = is_point_at_infinity();
762 bool_t result_is_infinity = infinity_predicate && (!lhs_infinity && !rhs_infinity);
763 result_is_infinity = result_is_infinity || (lhs_infinity && rhs_infinity);
765 return cycle_group(result_x, result_y, result_is_infinity);
781 result.
y = (-y).normalize();
787 *
this = *
this + other;
793 *
this = *
this - other;
823template <
typename Builder>
828 const bool unconditional_add)
833 for (
auto& scalar : scalars) {
834 if (scalar.lo.get_context() !=
nullptr) {
835 context = scalar.get_context();
839 for (
auto& point : base_points) {
840 if (point.get_context() !=
nullptr) {
847 for (
auto& s : scalars) {
848 num_bits =
std::max(num_bits, s.num_bits());
850 size_t num_rounds = (num_bits + TABLE_BITS - 1) / TABLE_BITS;
852 const size_t num_points = scalars.size();
862 std::vector<Element> operation_transcript;
864 Element offset_generator_accumulator = offset_generators[0];
866 for (
size_t i = 0; i < num_points; ++i) {
867 std::vector<Element> native_straus_table;
868 native_straus_table.emplace_back(offset_generators[i + 1]);
869 size_t table_size = 1ULL << TABLE_BITS;
870 for (
size_t j = 1; j < table_size; ++j) {
871 native_straus_table.emplace_back(native_straus_table[j - 1] + base_points[i].get_value());
873 native_straus_tables.emplace_back(native_straus_table);
875 for (
size_t i = 0; i < num_points; ++i) {
879 base_points[i].get_value(), offset_generators[i + 1], TABLE_BITS);
882 Element accumulator = offset_generators[0];
884 for (
size_t i = 0; i < num_rounds; ++i) {
886 for (
size_t j = 0; j < TABLE_BITS; ++j) {
888 accumulator = accumulator.dbl();
889 operation_transcript.emplace_back(accumulator);
890 offset_generator_accumulator = offset_generator_accumulator.dbl();
893 for (
size_t j = 0; j < num_points; ++j) {
896 native_straus_tables[j][
static_cast<size_t>(scalar_slices[j].slices_native[num_rounds - i - 1])];
898 accumulator += point;
900 operation_transcript.emplace_back(accumulator);
901 offset_generator_accumulator = offset_generator_accumulator +
Element(offset_generators[j + 1]);
907 Element::batch_normalize(&operation_transcript[0], operation_transcript.size());
909 std::vector<AffineElement> operation_hints;
910 operation_hints.reserve(operation_transcript.size());
911 for (
auto&
element : operation_transcript) {
916 const size_t hints_per_table = (1ULL << TABLE_BITS) - 1;
918 for (
size_t i = 0; i < num_points; ++i) {
921 tag =
OriginTag(tag, scalars[i].get_origin_tag(), base_points[i].get_origin_tag());
926 AffineElement* hint_ptr = &operation_hints[num_points * hints_per_table];
934 for (
size_t i = 0; i < num_rounds; ++i) {
935 for (
size_t j = 0; j < num_points; ++j) {
939 if (scalar_slice.has_value()) {
940 const cycle_group point = point_tables[j].read(scalar_slice.value());
941 points_to_add.emplace_back(point);
947 size_t point_counter = 0;
948 for (
size_t i = 0; i < num_rounds; ++i) {
950 for (
size_t j = 0; j < TABLE_BITS; ++j) {
951 accumulator = accumulator.
dbl(*hint_ptr);
956 for (
size_t j = 0; j < num_points; ++j) {
960 BB_ASSERT_EQ(scalar_slice.value().get_value(), scalar_slices[j].slices_native[num_rounds - i - 1]);
961 if (scalar_slice.has_value()) {
962 const auto& point = points_to_add[point_counter++];
963 if (!unconditional_add) {
964 x_coordinate_checks.push_back({ accumulator.
x, point.x });
975 field_t coordinate_check_product = 1;
976 for (
auto& [x1, x2] : x_coordinate_checks) {
977 auto x_diff = x2 - x1;
978 coordinate_check_product *= x_diff;
980 coordinate_check_product.
assert_is_not_zero(
"_variable_base_batch_mul_internal x-coordinate collision");
989 return { accumulator,
AffineElement(offset_generator_accumulator) };
1004template <
typename Builder>
1013 const size_t num_points = base_points.size();
1018 std::vector<AffineElement> plookup_base_points;
1022 for (
size_t i = 0; i < num_points; ++i) {
1024 tag =
OriginTag(tag, scalars[i].get_origin_tag());
1027 ASSERT(table_id.has_value());
1028 plookup_table_ids.emplace_back(table_id.value()[0]);
1029 plookup_table_ids.emplace_back(table_id.value()[1]);
1030 plookup_base_points.emplace_back(base_points[i]);
1032 plookup_scalars.emplace_back(scalars[i].lo);
1033 plookup_scalars.emplace_back(scalars[i].hi);
1037 Element offset_generator_accumulator = Group::point_at_infinity;
1038 for (
size_t i = 0; i < plookup_scalars.size(); ++i) {
1041 for (
size_t j = 0; j < lookup_data[ColumnIdx::C2].size(); ++j) {
1042 const auto x = lookup_data[ColumnIdx::C2][j];
1043 const auto y = lookup_data[ColumnIdx::C3][j];
1044 lookup_points.emplace_back(
cycle_group(x, y,
false));
1050 ASSERT(offset_1.has_value());
1051 offset_generator_accumulator += offset_1.value();
1059 std::vector<Element> operation_transcript;
1061 Element accumulator = lookup_points[0].get_value();
1062 for (
size_t i = 1; i < lookup_points.size(); ++i) {
1063 accumulator = accumulator + (lookup_points[i].get_value());
1064 operation_transcript.emplace_back(accumulator);
1067 Element::batch_normalize(&operation_transcript[0], operation_transcript.size());
1068 std::vector<AffineElement> operation_hints;
1069 operation_hints.reserve(operation_transcript.size());
1070 for (
auto&
element : operation_transcript) {
1078 for (
size_t i = 1; i < lookup_points.size(); ++i) {
1079 accumulator = accumulator.
unconditional_add(lookup_points[i], operation_hints[i - 1]);
1088 return { accumulator, offset_generator_accumulator };
1124template <
typename Builder>
1134 std::vector<AffineElement> fixed_base_points;
1138 for (
auto [point, scalar] :
zip_view(base_points, scalars)) {
1139 result_tag =
OriginTag(result_tag,
OriginTag(point.get_origin_tag(), scalar.get_origin_tag()));
1141 size_t num_bits = 0;
1142 for (
auto& s : scalars) {
1143 num_bits =
std::max(num_bits, s.num_bits());
1148 s.validate_scalar_is_in_field();
1152 bool num_bits_not_full_field_size = num_bits != NUM_BITS;
1157 bool can_unconditional_add =
true;
1158 bool has_non_constant_component =
false;
1159 Element constant_acc = Group::point_at_infinity;
1160 for (
size_t i = 0; i < scalars.size(); ++i) {
1161 bool scalar_constant = scalars[i].is_constant();
1162 bool point_constant = base_points[i].is_constant();
1163 if (scalar_constant && point_constant) {
1164 constant_acc += (base_points[i].get_value()) * (scalars[i].get_value());
1165 }
else if (!scalar_constant && point_constant) {
1166 if (base_points[i].get_value().is_point_at_infinity()) {
1170 if constexpr (IS_ULTRA) {
1171 if (!num_bits_not_full_field_size &&
1173 fixed_base_scalars.push_back(scalars[i]);
1174 fixed_base_points.push_back(base_points[i].get_value());
1177 variable_base_scalars.push_back(scalars[i]);
1178 variable_base_points.push_back(base_points[i]);
1181 fixed_base_scalars.push_back(scalars[i]);
1182 fixed_base_points.push_back(base_points[i].get_value());
1184 has_non_constant_component =
true;
1186 variable_base_scalars.push_back(scalars[i]);
1187 variable_base_points.push_back(base_points[i]);
1188 can_unconditional_add =
false;
1189 has_non_constant_component =
true;
1195 if (!has_non_constant_component) {
1197 result.set_origin_tag(result_tag);
1203 Element offset_accumulator = -constant_acc;
1204 const bool has_variable_points = !variable_base_points.empty();
1205 const bool has_fixed_points = !fixed_base_points.empty();
1208 const size_t num_offset_generators =
1209 variable_base_points.size() + fixed_base_points.size() + has_variable_points + has_fixed_points;
1211 context.generators->get(num_offset_generators, 0, OFFSET_GENERATOR_DOMAIN_SEPARATOR);
1214 if (has_fixed_points) {
1215 const auto [fixed_accumulator, offset_generator_delta] =
1216 _fixed_base_batch_mul_internal(fixed_base_scalars, fixed_base_points, offset_generators);
1217 offset_accumulator += offset_generator_delta;
1218 result = fixed_accumulator;
1221 if (has_variable_points) {
1223 offset_generators.data() + fixed_base_points.size(), offset_generators.size() - fixed_base_points.size()
1225 const auto [variable_accumulator, offset_generator_delta] =
1226 _variable_base_batch_mul_internal(variable_base_scalars,
1227 variable_base_points,
1228 offset_generators_for_variable_base_batch_mul,
1229 can_unconditional_add);
1230 offset_accumulator += offset_generator_delta;
1231 if (has_fixed_points) {
1235 result = variable_accumulator;
1249 if (!constant_acc.is_point_at_infinity() && can_unconditional_add) {
1271 return batch_mul({ *
this }, { scalar });
1282 return batch_mul({ *
this }, { scalar });
1293 this->standardize();
1295 const auto equal = (x == other.
x) && (y == other.
y) && (this->_is_infinity == other.
_is_infinity);
1301 this->standardize();
1303 x.assert_equal(other.
x, msg);
1304 y.assert_equal(other.
y, msg);
1308template <
typename Builder>
1315 auto _is_infinity_res =
1324 if (x_res.is_constant() && !y_res.is_constant()) {
#define BB_ASSERT_EQ(actual, expected,...)
#define ASSERT(expression,...)
Container type for lookup table reads.
static std::optional< std::array< MultiTableId, 2 > > get_lookup_table_ids_for_point(const affine_element &input)
Given a point, return (if it exists) the 2 MultiTableId's that correspond to the LO_SCALAR,...
static bool lookup_table_exists_for_point(const affine_element &input)
Given a point, do we have a precomputed lookup table for this point?
static std::optional< affine_element > get_generator_offset_for_table_id(MultiTableId table_id)
Given a table id, return the offset generator term that will be present in the final scalar mul outpu...
Implements boolean logic in-circuit.
bool_t normalize() const
A bool_t element is normalized if witness_inverted == false. For a given *this, output its normalized...
static bool_t conditional_assign(const bool_t< Builder > &predicate, const bool_t &lhs, const bool_t &rhs)
Implements the ternary operator - if predicate == true then return lhs, else return rhs.
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....
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()
Get the point to the standard form. If the point is a point at infinity, ensure the coordinates are (...
static batch_mul_internal_output _fixed_base_batch_mul_internal(std::span< cycle_scalar > scalars, std::span< AffineElement > base_points, std::span< AffineElement const > offset_generators)
Internal algorithm to perform a fixed-base batch mul for ULTRA Builder.
cycle_group get_standard_form()
Get point in standard form. If the point is a point at infinity, ensure the coordinates are (0,...
typename Curve::Element Element
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
Will evaluate ECC point subtraction over *this and other. Uses incomplete addition formula If incompl...
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 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) const
cycle_group & operator+=(const cycle_group &other)
void validate_is_on_curve() const
On-curve check.
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 algorithm to perform a variable-base batch mul.
cycle_group(Builder *_context=nullptr)
Construct a new cycle group<Builder>::cycle group object defaults to a constant point at infinity.
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
void assert_equal(cycle_group &other, std::string const &msg="cycle_group::assert_equal")
void set_point_at_infinity(const bool_t &is_infinity)
Set the point to the point at infinity. Depending on constant'ness of the predicate put the coordinat...
cycle_group dbl(const std::optional< AffineElement > hint=std::nullopt) const
Evaluates a doubling. Uses Ultra double gate.
cycle_group operator+(const cycle_group &other) const
Will evaluate ECC point addition over *this and other. This method uses complete addition i....
typename Curve::AffineElement AffineElement
cycle_group unconditional_subtract(const cycle_group &other, const std::optional< AffineElement > hint=std::nullopt) const
will evaluate ECC point subtraction over *this and other. Incomplete addition formula edge cases are ...
Builder * get_context() const
cycle_group checked_unconditional_add(const cycle_group &other, const std::optional< AffineElement > hint=std::nullopt) const
Will evaluate ECC point addition over *this and other. Uses incomplete addition formula If incomplete...
static cycle_group batch_mul(const std::vector< cycle_group > &base_points, const std::vector< BigScalarField > &scalars, GeneratorContext context={})
cycle_group unconditional_add(const cycle_group &other, const std::optional< AffineElement > hint=std::nullopt) const
Will evaluate ECC point addition over *this and other. Incomplete addition formula edge cases are NOT...
cycle_scalar represents a member of the cycle curve SCALAR FIELD. This is NOT the native circuit fiel...
static constexpr size_t LO_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 field_t from_witness_index(Builder *ctx, uint32_t witness_index)
static void evaluate_polynomial_identity(const field_t &a, const field_t &b, const field_t &c, const field_t &d)
Given a, b, c, d, constrain a * b + c + d = 0 by creating a big_mul_gate.
static field_t conditional_assign(const bool_t< Builder > &predicate, const field_t &lhs, const field_t &rhs)
If predicate == true then return lhs, else return rhs.
Builder * get_context() const
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
field_t normalize() const
Return a new element, where the in-circuit witness contains the actual represented value (multiplicat...
static field_t from_witness(Builder *ctx, const bb::fr &input)
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.
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_straus_lookup_table_hints(const Element &base_point, const Element &offset_generator, size_t table_bits)
Compute the output points generated when computing the Straus lookup table.
straus_scalar_slice decomposes an input scalar into table_bits bit-slices. Used in batch_mul,...
StrictMock< MockContext > context
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...
Univariate< Fr, domain_end, domain_start, skip_count > operator*(const Fr &ff, const Univariate< Fr, domain_end, domain_start, skip_count > &uv)
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 constexpr field zero()
Stores temporary variables produced by internal multiplication algorithms.
void throw_or_abort(std::string const &err)