138 const uint32_t total_number_of_muls)
140 const size_t num_vm_entries = vm_operations.size();
142 const size_t transcript_size = num_vm_entries + 2;
148 std::vector<FF> inverse_trace_x(num_vm_entries);
149 std::vector<FF> inverse_trace_y(num_vm_entries);
150 std::vector<FF> transcript_msm_x_inverse_trace(num_vm_entries);
151 std::vector<FF> add_lambda_denominator(num_vm_entries);
152 std::vector<FF> add_lambda_numerator(num_vm_entries);
153 std::vector<FF> msm_count_at_transition_inverse_trace(num_vm_entries);
163 .
pc = total_number_of_muls,
167 .is_accumulator_empty =
true,
178 for (
size_t i = 0; i < num_vm_entries; i++) {
181 updated_state = state;
185 const bool z1_zero = is_mul ? entry.
z1 == 0 :
true;
186 const bool z2_zero = is_mul ? entry.
z2 == 0 :
true;
188 const bool base_point_infinity = entry.
base_point.is_point_at_infinity();
189 uint32_t num_muls = 0;
192 num_muls =
static_cast<uint32_t
>(!z1_zero) +
static_cast<uint32_t
>(!z2_zero);
193 if (base_point_infinity) {
197 updated_state.
pc = state.pc - num_muls;
207 const bool last_row = (i == (num_vm_entries - 1));
209 const bool next_not_msm = last_row || !vm_operations[i + 1].op_code.mul;
215 const bool msm_transition = is_mul && next_not_msm && (state.count + num_muls > 0);
218 const bool current_ongoing_msm = is_mul && !next_not_msm;
220 updated_state.
count = current_ongoing_msm ? state.count + num_muls : 0;
229 if (msm_transition) {
232 msm_accumulator_trace[i] = Element::infinity();
233 intermediate_accumulator_trace[i] = Element::infinity();
243 msm_count_at_transition_inverse_trace[i] = ((state.count + num_muls) == 0) ? 0 :
FF(state.count + num_muls);
247 accumulator_trace[i] = state.accumulator;
248 msm_accumulator_trace[i] = msm_transition ? updated_state.
msm_accumulator : Element::infinity();
249 intermediate_accumulator_trace[i] =
252 state = updated_state;
254 if (is_mul && next_not_msm) {
263 transcript_state, accumulator_trace, msm_accumulator_trace, intermediate_accumulator_trace);
267 for (
size_t i = 0; i < accumulator_trace.size(); ++i) {
274 if (msm_transition || is_add) {
278 intermediate_accumulator_trace[i],
279 transcript_msm_x_inverse_trace[i],
280 msm_accumulator_trace[i],
281 accumulator_trace[i],
288 intermediate_accumulator_trace[i],
289 accumulator_trace[i],
290 add_lambda_numerator[i],
291 add_lambda_denominator[i]);
295 add_lambda_numerator[i] = 0;
296 add_lambda_denominator[i] = 0;
297 inverse_trace_x[i] = 0;
298 inverse_trace_y[i] = 0;
307 FF::batch_invert(&msm_count_at_transition_inverse_trace[0], num_vm_entries);
310 for (
size_t i = 0; i < num_vm_entries; ++i) {
322 return transcript_state;
572 const Element& intermediate_accumulator,
574 FF& add_lambda_numerator,
575 FF& add_lambda_denominator)
579 const bool vm_infinity = vm_point.is_point_at_infinity();
580 const bool accumulator_infinity = accumulator.is_point_at_infinity();
583 const FF vm_x = vm_infinity ? 0 : vm_point.x;
584 const FF vm_y = vm_infinity ? 0 : vm_point.y;
587 const FF accumulator_x = accumulator_infinity ? 0 : accumulator.x;
588 const FF accumulator_y = accumulator_infinity ? 0 : accumulator.y;
594 if ((accumulator_x == vm_x) && (accumulator_y == vm_y) && !vm_infinity && !accumulator_infinity) {
596 add_lambda_denominator = vm_y + vm_y;
597 add_lambda_numerator = vm_x * vm_x * 3;
598 }
else if ((accumulator_x != vm_x) && !vm_infinity && !accumulator_infinity) {
600 add_lambda_denominator = accumulator_x - vm_x;
601 add_lambda_numerator = accumulator_y - vm_y;