39 const Fq& previous_accumulator,
40 const Fq& batching_challenge_v,
41 const Fq& evaluation_input_x)
50 auto uint512_t_to_limbs = [](
const uint512_t& original) {
60 auto split_wide_limb_into_2_limbs = [](
const Fr& wide_limb) {
72 auto split_limb_into_microlimbs = [](
const Fr& limb,
const size_t num_bits) {
79 for (
size_t i = 0; i < num_full_micro_limbs; ++i) {
84 if (last_limb_bits > 0) {
90 microlimbs[num_full_micro_limbs + 1] =
uint256_t(microlimbs[num_full_micro_limbs])
112 auto uint_previous_accumulator =
uint512_t(previous_accumulator);
120 auto uint_v_squared =
uint512_t(v_squared);
122 auto uint_v_quarted =
uint512_t(v_quarted);
132 auto [p_x_0, p_x_1] = split_wide_limb_into_2_limbs(ultra_op.
x_lo);
133 auto [p_x_2, p_x_3] = split_wide_limb_into_2_limbs(ultra_op.
x_hi);
135 auto [p_y_0, p_y_1] = split_wide_limb_into_2_limbs(ultra_op.
y_lo);
136 auto [p_y_2, p_y_3] = split_wide_limb_into_2_limbs(ultra_op.
y_hi);
140 auto z_1_limbs = split_wide_limb_into_2_limbs(ultra_op.
z_1);
141 auto z_2_limbs = split_wide_limb_into_2_limbs(ultra_op.
z_2);
149 base_p_y * v_squared +
151 base_z_2 * v_quarted;
154 uint512_t quotient_by_modulus = uint_previous_accumulator * uint_x +
157 uint_p_y * uint_v_squared +
158 uint_z1 * uint_v_cubed +
159 uint_z2 * uint_v_quarted -
174 Fr low_wide_relation_limb_part_1 =
175 previous_accumulator_limbs[0] * x_witnesses[0] +
177 p_x_limbs[0] * v_witnesses[0] +
178 p_y_limbs[0] * v_squared_witnesses[0] +
179 z_1_limbs[0] * v_cubed_witnesses[0] +
180 z_2_limbs[0] * v_quarted_witnesses[0] +
184 Fr low_wide_relation_limb =
185 low_wide_relation_limb_part_1 +
186 (previous_accumulator_limbs[1] * x_witnesses[0] +
187 previous_accumulator_limbs[0] * x_witnesses[1] +
188 p_x_limbs[0] * v_witnesses[1] +
189 p_x_limbs[1] * v_witnesses[0] +
190 p_y_limbs[0] * v_squared_witnesses[1] +
191 p_y_limbs[1] * v_squared_witnesses[0] +
192 z_1_limbs[0] * v_cubed_witnesses[1] +
193 z_1_limbs[1] * v_cubed_witnesses[0] +
194 z_2_limbs[0] * v_quarted_witnesses[1] +
195 z_2_limbs[1] * v_quarted_witnesses[0] +
209 Fr high_wide_relation_limb_part_1 =
210 low_wide_relation_limb_divided +
211 previous_accumulator_limbs[2] * x_witnesses[0] +
212 previous_accumulator_limbs[1] * x_witnesses[1] +
213 previous_accumulator_limbs[0] * x_witnesses[2] +
214 p_x_limbs[0] * v_witnesses[2] +
215 p_x_limbs[1] * v_witnesses[1] +
216 p_x_limbs[2] * v_witnesses[0] +
217 p_y_limbs[0] * v_squared_witnesses[2] +
218 p_y_limbs[1] * v_squared_witnesses[1] +
219 p_y_limbs[2] * v_squared_witnesses[0] +
220 z_1_limbs[0] * v_cubed_witnesses[2] +
221 z_1_limbs[1] * v_cubed_witnesses[1] +
222 z_2_limbs[0] * v_quarted_witnesses[2] +
223 z_2_limbs[1] * v_quarted_witnesses[1] +
229 Fr high_wide_relation_limb =
230 high_wide_relation_limb_part_1 +
231 (previous_accumulator_limbs[3] * x_witnesses[0] +
232 previous_accumulator_limbs[2] * x_witnesses[1] +
233 previous_accumulator_limbs[1] * x_witnesses[2] +
234 previous_accumulator_limbs[0] * x_witnesses[3] +
235 p_x_limbs[0] * v_witnesses[3] +
236 p_x_limbs[1] * v_witnesses[2] +
237 p_x_limbs[2] * v_witnesses[1] +
238 p_x_limbs[3] * v_witnesses[0] +
239 p_y_limbs[0] * v_squared_witnesses[3] +
240 p_y_limbs[1] * v_squared_witnesses[2] +
241 p_y_limbs[2] * v_squared_witnesses[1] +
242 p_y_limbs[3] * v_squared_witnesses[0] +
243 z_1_limbs[0] * v_cubed_witnesses[3] +
244 z_1_limbs[1] * v_cubed_witnesses[2] +
245 z_2_limbs[0] * v_quarted_witnesses[3] +
246 z_2_limbs[1] * v_quarted_witnesses[2] +
258 auto high_wide_relation_limb_divided = high_wide_relation_limb *
SHIFT_2_INVERSE;
270 for (
size_t i = 0; i < last_limb_index; i++) {
271 P_x_microlimbs[i] = split_limb_into_microlimbs(p_x_limbs[i],
NUM_LIMB_BITS);
272 P_y_microlimbs[i] = split_limb_into_microlimbs(p_y_limbs[i],
NUM_LIMB_BITS);
273 current_accumulator_microlimbs[i] = split_limb_into_microlimbs(remainder_limbs[i],
NUM_LIMB_BITS);
274 quotient_microlimbs[i] = split_limb_into_microlimbs(quotient_limbs[i],
NUM_LIMB_BITS);
278 P_x_microlimbs[last_limb_index] = split_limb_into_microlimbs(p_x_limbs[last_limb_index],
NUM_LAST_LIMB_BITS);
279 P_y_microlimbs[last_limb_index] = split_limb_into_microlimbs(p_y_limbs[last_limb_index],
NUM_LAST_LIMB_BITS);
280 current_accumulator_microlimbs[last_limb_index] =
282 quotient_microlimbs[last_limb_index] =
287 z_1_microlimbs[i] = split_limb_into_microlimbs(z_1_limbs[i],
NUM_LIMB_BITS);
288 z_2_microlimbs[i] = split_limb_into_microlimbs(z_2_limbs[i],
NUM_LIMB_BITS);
298 .P_x_limbs = p_x_limbs,
299 .P_x_microlimbs = P_x_microlimbs,
300 .P_y_limbs = p_y_limbs,
301 .P_y_microlimbs = P_y_microlimbs,
302 .z_1_limbs = z_1_limbs,
303 .z_1_microlimbs = z_1_microlimbs,
304 .z_2_limbs = z_2_limbs,
305 .z_2_microlimbs = z_2_microlimbs,
306 .previous_accumulator = previous_accumulator_limbs,
307 .current_accumulator = remainder_limbs,
308 .current_accumulator_microlimbs = current_accumulator_microlimbs,
309 .quotient_binary_limbs = quotient_limbs,
310 .quotient_microlimbs = quotient_microlimbs,
311 .relation_wide_limbs = { low_wide_relation_limb_divided, high_wide_relation_limb_divided },
312 .relation_wide_microlimbs = { split_limb_into_microlimbs(low_wide_relation_limb_divided,
314 split_limb_into_microlimbs(high_wide_relation_limb_divided,
478 size_t wire_index = starting_wire;
479 for (
auto element : input) {
518 const auto& ultra_ops = ecc_op_queue->get_ultra_ops();
520 Fq current_accumulator(0);
521 if (ultra_ops.empty()) {
529 for (
auto& wire :
wires) {
535 auto process_random_op = [&](
const UltraOp& ultra_op) {
536 BB_ASSERT(ultra_op.op_code.is_random_op,
"function should only be called to process a random op");
552 process_random_op(ultra_ops[i]);
567 for (
const auto& ultra_op : std::ranges::reverse_view(ultra_ops_span)) {
568 if (ultra_op.op_code.value() == 0) {
573 const auto [x_fq, y_fq] = ultra_op.get_base_point_standard_form();
574 current_accumulator +=
575 Fq(ultra_op.op_code.value()) +
580 accumulator_trace.push_back(current_accumulator);
584 Fq final_accumulator_state = accumulator_trace.back();
585 accumulator_trace.pop_back();
589 for (
const auto& ultra_op : ultra_ops_span) {
590 if (ultra_op.op_code.value() == 0) {
614 Fq previous_accumulator{ 0 };
616 if (!accumulator_trace.empty()) {
617 previous_accumulator = accumulator_trace.back();
618 accumulator_trace.pop_back();
632 for (
size_t i = ops_end; i < ultra_ops.size(); ++i) {
633 process_random_op(ultra_ops[i]);