22 const std::vector<Fr>& _scalars)
27 const auto [points, scalars] = handle_points_at_infinity(_points, _scalars);
30 for (
const auto& point : points) {
35 for (
const auto& scalar : scalars) {
36 wnaf_entries.emplace_back(compute_wnaf<max_num_bits>(scalar));
39 constexpr size_t num_bits = (max_num_bits == 0) ? (
Fr::modulus.
get_msb() + 1) : (max_num_bits);
41 const auto offset_generators = compute_offset_generators(num_rounds * 4 - 3);
43 element accumulator = offset_generators.first + point_tables[0][wnaf_entries[0][0]];
44 for (
size_t i = 1; i < points.size(); ++i) {
45 accumulator += point_tables[i][wnaf_entries[i][0]];
48 for (
size_t i = 1; i < num_rounds; ++i) {
49 accumulator = accumulator.
dbl();
50 accumulator = accumulator.
dbl();
52 for (
size_t j = 0; j < points.size(); ++j) {
53 to_add.emplace_back(point_tables[j][wnaf_entries[j][i]]);
58 for (
size_t i = 0; i < points.size(); ++i) {
59 element skew = accumulator - points[i];
60 Fq out_x = accumulator.
x.conditional_select(skew.
x,
bool_ct(wnaf_entries[i][num_rounds]));
61 Fq out_y = accumulator.
y.conditional_select(skew.
y,
bool_ct(wnaf_entries[i][num_rounds]));
62 accumulator =
element(out_x, out_y);
64 accumulator -= offset_generators.second;