45 std::vector<Fr> scalars;
47 using NativeFr =
typename Fr::native;
48 auto running_scalar = NativeFr::one();
50 auto native_offset_generator = element::compute_table_offset_generator();
51 Fr last_scalar =
Fr(0);
52 NativeFr generator_coefficient = NativeFr(2).pow(_points.size());
53 auto generator_coefficient_inverse = generator_coefficient.invert();
55 for (
size_t i = 0; i < _points.size(); i++) {
56 scalars.push_back(_scalars[i]);
58 points.push_back(_points[i] + (native_offset_generator * running_scalar));
60 last_scalar += _scalars[i] * (running_scalar * generator_coefficient_inverse);
62 running_scalar += running_scalar;
66 scalars.push_back(-last_scalar);
67 if constexpr (Fr::is_composite) {
68 scalars.back().self_reduce();
71 points.push_back(
element(native_offset_generator * generator_coefficient));
73 return { points, scalars };
86 std::vector<Fr> scalars;
89 for (
auto [_point, _scalar] :
zip_view(_points, _scalars)) {
90 bool_ct is_point_at_infinity = _point.is_point_at_infinity();
95 if (_scalar.get_value() == 0 && _scalar.is_constant()) {
99 Fq updated_x = Fq::conditional_assign(is_point_at_infinity, one.
x, _point.x);
100 Fq updated_y = Fq::conditional_assign(is_point_at_infinity, one.
y, _point.y);
101 element point(updated_x, updated_y);
102 Fr scalar = Fr::conditional_assign(is_point_at_infinity, 0, _scalar);
104 points.push_back(point);
105 scalars.push_back(scalar);
110 return { points, scalars };