83 size_t size_override = 0,
84 uint32_t* duplicate_count_out =
nullptr)
94 size_t domain_size = size_override == 0 ? full_polynomials.
get_polynomial_size() : size_override;
99 const size_t active_size = domain_size - gp_start;
114 const bool count_duplicates = duplicate_count_out !=
nullptr;
115 std::vector<uint32_t> thread_duplicate_counts(count_duplicates ? thread_data.
num_threads : 0, 0);
120 BB_BENCH_TRACY_NAME(
"GrandProduct::step1_numerator_denominator");
121 const size_t start = thread_data.start[thread_idx];
122 const size_t end = thread_data.end[thread_idx];
123 typename Flavor::AllValues row;
124 uint32_t local_duplicates = 0;
125 for (size_t i = start; i < end; ++i) {
126 const size_t poly_idx = i + gp_start;
128 if constexpr (IsUltraOrMegaHonk<Flavor>) {
129 row = full_polynomials.get_row_for_permutation_arg(poly_idx);
131 row = full_polynomials.get_row(poly_idx);
134 GrandProdRelation::template compute_grand_product_numerator<Accumulator>(row, relation_parameters);
136 GrandProdRelation::template compute_grand_product_denominator<Accumulator>(row, relation_parameters);
137 if (count_duplicates && numerator[i] == denominator[i]) {
141 if (count_duplicates) {
142 thread_duplicate_counts[thread_idx] = local_duplicates;
146 if (count_duplicates) {
147 uint32_t total_duplicates = 0;
148 for (
const uint32_t c : thread_duplicate_counts) {
149 total_duplicates += c;
151 *duplicate_count_out = total_duplicates;
169 std::vector<FF> partial_numerators(thread_data.num_threads);
170 std::vector<FF> partial_denominators(thread_data.num_threads);
172 parallel_for(thread_data.num_threads, [&](
size_t thread_idx) {
173 BB_BENCH_TRACY_NAME(
"GrandProduct::step2a_subproducts");
174 const size_t start = thread_data.start[thread_idx];
175 const size_t end = thread_data.end[thread_idx];
176 for (size_t i = start; i < end - 1; ++i) {
177 numerator.at(i + 1) *= numerator[i];
178 denominator.at(i + 1) *= denominator[i];
180 partial_numerators[thread_idx] = numerator[end - 1];
181 partial_denominators[thread_idx] = denominator[end - 1];
187 parallel_for(thread_data.num_threads, [&](
size_t thread_idx) {
188 BB_BENCH_TRACY_NAME(
"GrandProduct::step2b_scale_and_invert");
189 const size_t start = thread_data.start[thread_idx];
190 const size_t end = thread_data.end[thread_idx];
191 if (thread_idx > 0) {
192 FF numerator_scaling = 1;
193 FF denominator_scaling = 1;
195 for (size_t j = 0; j < thread_idx; ++j) {
196 numerator_scaling *= partial_numerators[j];
197 denominator_scaling *= partial_denominators[j];
199 for (size_t i = start; i < end; ++i) {
200 numerator.at(i) = numerator[i] * numerator_scaling;
201 denominator.at(i) = denominator[i] * denominator_scaling;
213 auto& grand_product_polynomial = GrandProdRelation::get_grand_product_polynomial(full_polynomials);
215 BB_ASSERT(grand_product_polynomial.is_shiftable());
224 parallel_for(thread_data.num_threads, [&](
size_t thread_idx) {
225 BB_BENCH_TRACY_NAME(
"GrandProduct::step3_quotient");
226 const size_t start = thread_data.start[thread_idx];
227 const size_t end = thread_data.end[thread_idx];
228 for (size_t i = start; i < end; ++i) {
229 grand_product_polynomial.at(gp_start + i + 1) = numerator[i] * denominator[i];
void compute_grand_product(typename Flavor::ProverPolynomials &full_polynomials, bb::RelationParameters< typename Flavor::FF > &relation_parameters, size_t size_override=0, uint32_t *duplicate_count_out=nullptr)
Compute a grand product polynomial, grand_product_polynomial, which for historical reasons is sometim...