73 using View =
typename Accumulator::View;
75 const auto& precompute_round = View(in.precompute_round);
76 const auto precompute_round2 = precompute_round + precompute_round;
77 const auto precompute_round4 = precompute_round2 + precompute_round2;
79 const auto& gamma = params.gamma;
80 const auto& beta = params.beta;
81 const auto& beta_sqr = params.beta_sqr;
82 const auto& beta_cube = params.beta_cube;
83 const auto& precompute_pc = View(in.precompute_pc);
84 const auto& precompute_select = View(in.precompute_select);
100 Accumulator numerator(1);
102 const auto& s0 = View(in.precompute_s1hi);
103 const auto& s1 = View(in.precompute_s1lo);
105 auto wnaf_slice = s0 + s0;
106 wnaf_slice += wnaf_slice;
109 const auto wnaf_slice_input0 = wnaf_slice + gamma + precompute_pc * beta + precompute_round4 * beta_sqr;
110 numerator *= wnaf_slice_input0;
113 const auto& s0 = View(in.precompute_s2hi);
114 const auto& s1 = View(in.precompute_s2lo);
116 auto wnaf_slice = s0 + s0;
117 wnaf_slice += wnaf_slice;
120 const auto wnaf_slice_input1 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 1) * beta_sqr;
121 numerator *= wnaf_slice_input1;
124 const auto& s0 = View(in.precompute_s3hi);
125 const auto& s1 = View(in.precompute_s3lo);
127 auto wnaf_slice = s0 + s0;
128 wnaf_slice += wnaf_slice;
131 const auto wnaf_slice_input2 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 2) * beta_sqr;
132 numerator *= wnaf_slice_input2;
135 const auto& s0 = View(in.precompute_s4hi);
136 const auto& s1 = View(in.precompute_s4lo);
138 auto wnaf_slice = s0 + s0;
139 wnaf_slice += wnaf_slice;
141 const auto wnaf_slice_input3 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 3) * beta_sqr;
142 numerator *= wnaf_slice_input3;
146 const auto& skew = View(in.precompute_skew);
147 const auto& precompute_point_transition = View(in.precompute_point_transition);
148 const auto skew_input =
149 precompute_point_transition * (skew + gamma + precompute_pc * beta + (precompute_round4 + 4) * beta_sqr) +
150 (-precompute_point_transition + 1);
151 numerator *= skew_input;
158 const auto& eccvm_set_permutation_delta = params.eccvm_set_permutation_delta;
162 numerator *= precompute_select * (-eccvm_set_permutation_delta + 1) + eccvm_set_permutation_delta;
179 const auto& table_x = View(in.precompute_tx);
180 const auto& table_y = View(in.precompute_ty);
182 const auto& precompute_skew = View(in.precompute_skew);
183 const auto negative_inverse_seven = []() {
185 static constexpr FF negative_inverse_seven =
FF(-7).
invert();
186 return negative_inverse_seven;
189 return negative_inverse_seven;
193 precompute_skew * negative_inverse_seven();
195 const auto& wnaf_scalar_sum = View(in.precompute_scalar_sum);
196 const auto w0 = convert_to_wnaf<Accumulator>(View(in.precompute_s1hi), View(in.precompute_s1lo));
197 const auto w1 = convert_to_wnaf<Accumulator>(View(in.precompute_s2hi), View(in.precompute_s2lo));
198 const auto w2 = convert_to_wnaf<Accumulator>(View(in.precompute_s3hi), View(in.precompute_s3lo));
199 const auto w3 = convert_to_wnaf<Accumulator>(View(in.precompute_s4hi), View(in.precompute_s4lo));
202 row_slice += row_slice;
203 row_slice += row_slice;
204 row_slice += row_slice;
205 row_slice += row_slice;
207 row_slice += row_slice;
208 row_slice += row_slice;
209 row_slice += row_slice;
210 row_slice += row_slice;
212 row_slice += row_slice;
213 row_slice += row_slice;
214 row_slice += row_slice;
215 row_slice += row_slice;
218 auto scalar_sum_full = wnaf_scalar_sum + wnaf_scalar_sum;
219 scalar_sum_full += scalar_sum_full;
220 scalar_sum_full += scalar_sum_full;
221 scalar_sum_full += scalar_sum_full;
222 scalar_sum_full += scalar_sum_full;
223 scalar_sum_full += scalar_sum_full;
224 scalar_sum_full += scalar_sum_full;
225 scalar_sum_full += scalar_sum_full;
226 scalar_sum_full += scalar_sum_full;
227 scalar_sum_full += scalar_sum_full;
228 scalar_sum_full += scalar_sum_full;
229 scalar_sum_full += scalar_sum_full;
230 scalar_sum_full += scalar_sum_full;
231 scalar_sum_full += scalar_sum_full;
232 scalar_sum_full += scalar_sum_full;
233 scalar_sum_full += scalar_sum_full;
235 row_slice + adjusted_skew;
237 auto precompute_point_transition = View(in.precompute_point_transition);
239 auto point_table_init_read =
240 (precompute_pc + table_x * beta + table_y * beta_sqr + scalar_sum_full * beta_cube);
241 point_table_init_read =
242 precompute_point_transition * (point_table_init_read + gamma) + (-precompute_point_transition + 1);
244 numerator *= point_table_init_read;
264 const auto& lagrange_first = View(in.lagrange_first);
265 const auto& partial_msm_transition_shift = View(in.msm_transition_shift);
266 const auto msm_transition_shift = (-lagrange_first + 1) * partial_msm_transition_shift;
267 const auto& msm_pc_shift = View(in.msm_pc_shift);
269 const auto& msm_x_shift = View(in.msm_accumulator_x_shift);
270 const auto& msm_y_shift = View(in.msm_accumulator_y_shift);
271 const auto& msm_size = View(in.msm_size_of_msm);
285 auto msm_result_write = msm_pc_shift + msm_x_shift * beta + msm_y_shift * beta_sqr + msm_size * beta_cube;
288 msm_result_write = msm_transition_shift * (msm_result_write + gamma) + (-msm_transition_shift + 1);
289 numerator *= msm_result_write;
298 using View =
typename Accumulator::View;
302 const auto& gamma = params.gamma;
303 const auto& beta = params.beta;
304 const auto& beta_sqr = params.beta_sqr;
305 const auto& beta_cube = params.beta_cube;
306 const auto& msm_pc = View(in.msm_pc);
307 const auto& msm_count = View(in.msm_count);
308 const auto& msm_round = View(in.msm_round);
315 Accumulator denominator(1);
317 const auto& add1 = View(in.msm_add1);
318 const auto& msm_slice1 = View(in.msm_slice1);
320 auto wnaf_slice_output1 =
321 add1 * (msm_slice1 + gamma + (msm_pc - msm_count) * beta + msm_round * beta_sqr) + (-add1 + 1);
322 denominator *= wnaf_slice_output1;
325 const auto& add2 = View(in.msm_add2);
326 const auto& msm_slice2 = View(in.msm_slice2);
328 auto wnaf_slice_output2 =
329 add2 * (msm_slice2 + gamma + (msm_pc - msm_count - 1) * beta + msm_round * beta_sqr) + (-add2 + 1);
330 denominator *= wnaf_slice_output2;
333 const auto& add3 = View(in.msm_add3);
334 const auto& msm_slice3 = View(in.msm_slice3);
336 auto wnaf_slice_output3 =
337 add3 * (msm_slice3 + gamma + (msm_pc - msm_count - 2) * beta + msm_round * beta_sqr) + (-add3 + 1);
338 denominator *= wnaf_slice_output3;
341 const auto& add4 = View(in.msm_add4);
342 const auto& msm_slice4 = View(in.msm_slice4);
343 auto wnaf_slice_output4 =
344 add4 * (msm_slice4 + gamma + (msm_pc - msm_count - 3) * beta + msm_round * beta_sqr) + (-add4 + 1);
345 denominator *= wnaf_slice_output4;
359 const auto& transcript_pc = View(in.transcript_pc);
361 const auto& transcript_Px = View(in.transcript_Px);
362 const auto& transcript_Py = View(in.transcript_Py);
363 const auto& z1 = View(in.transcript_z1);
364 const auto& z2 = View(in.transcript_z2);
365 const auto& z1_zero = View(in.transcript_z1zero);
366 const auto& z2_zero = View(in.transcript_z2zero);
367 const auto& base_infinity = View(in.transcript_base_infinity);
368 const auto& transcript_mul = View(in.transcript_mul);
370 const auto& lookup_first = (-z1_zero + 1);
371 const auto& lookup_second = (-z2_zero + 1);
374 auto transcript_input1 =
375 transcript_pc + transcript_Px * beta + transcript_Py * beta_sqr + z1 * beta_cube;
376 auto transcript_input2 = (transcript_pc - 1) + transcript_Px * cube_root_unity * beta -
377 transcript_Py * beta_sqr + z2 * beta_cube;
395 transcript_input1 = (transcript_input1 + gamma) * lookup_first + (-lookup_first + 1);
396 transcript_input2 = (transcript_input2 + gamma) * lookup_second + (-lookup_second + 1);
399 auto transcript_product = (transcript_input1 * transcript_input2) * (-base_infinity + 1) + base_infinity;
402 auto point_table_init_write = transcript_mul * transcript_product + (-transcript_mul + 1);
403 denominator *= point_table_init_write;
421 const auto& transcript_pc_shift = View(in.transcript_pc_shift);
422 const auto& transcript_msm_x = View(in.transcript_msm_x);
423 const auto& transcript_msm_y = View(in.transcript_msm_y);
424 const auto& transcript_msm_transition = View(in.transcript_msm_transition);
425 const auto& transcript_msm_count = View(in.transcript_msm_count);
426 const auto& z1_zero = View(in.transcript_z1zero);
427 const auto& z2_zero = View(in.transcript_z2zero);
428 const auto& transcript_mul = View(in.transcript_mul);
429 const auto& base_infinity = View(in.transcript_base_infinity);
432 auto full_msm_count =
433 transcript_msm_count + transcript_mul * ((-z1_zero + 1) + (-z2_zero + 1)) * (-base_infinity + 1);
435 auto msm_result_read =
436 transcript_pc_shift + transcript_msm_x * beta + transcript_msm_y * beta_sqr + full_msm_count * beta_cube;
437 msm_result_read = transcript_msm_transition * (msm_result_read + gamma) + (-transcript_msm_transition + 1);
438 denominator *= msm_result_read;
456 const AllEntities& in,
457 const Parameters& params,
458 const FF& scaling_factor)
461 using View =
typename Accumulator::View;
462 using ShortView =
typename std::tuple_element_t<1, ContainerOverSubrelations>::View;
465 Accumulator numerator_evaluation = compute_grand_product_numerator<Accumulator>(in, params);
468 Accumulator denominator_evaluation = compute_grand_product_denominator<Accumulator>(in, params);
470 const auto& lagrange_first = View(in.lagrange_first);
471 const auto& lagrange_last = View(in.lagrange_last);
472 const auto& lagrange_last_short = ShortView(in.lagrange_last);
474 const auto& z_perm = View(in.z_perm);
475 const auto& z_perm_shift = View(in.z_perm_shift);
476 const auto& z_perm_shift_short = ShortView(in.z_perm_shift);
480 ((z_perm + lagrange_first) * numerator_evaluation - (z_perm_shift + lagrange_last) * denominator_evaluation) *
484 std::get<1>(accumulator) += lagrange_last_short * z_perm_shift_short * scaling_factor;