2#include "barretenberg/common/ref_vector.hpp"
3#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp"
4#include "barretenberg/polynomials/polynomial.hpp"
7namespace proof_system::honk::permutation_library {
45template <
typename Flavor,
typename GrandProdRelation>
46void compute_permutation_grand_product(
const size_t circuit_size,
47 auto& full_polynomials,
50 using FF =
typename Flavor::FF;
52 using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::SumcheckArrayOfValuesOverSubrelations>;
57 Polynomial numerator = Polynomial{ circuit_size };
58 Polynomial denominator = Polynomial{ circuit_size };
62 static constexpr size_t MIN_CIRCUIT_SIZE_TO_MULTITHREAD = 64;
63 const size_t num_threads = circuit_size >= MIN_CIRCUIT_SIZE_TO_MULTITHREAD
64 ? (circuit_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1)
66 const size_t block_size = circuit_size / num_threads;
67 parallel_for(num_threads, [&](
size_t thread_idx) {
68 const size_t start = thread_idx * block_size;
69 const size_t end = (thread_idx + 1) * block_size;
70 for (
size_t i = start; i < end; ++i) {
73 for (
auto [eval, poly] :
zip_view(evaluations.get_all(), full_polynomials.get_all())) {
74 eval = poly.size() > i ? poly[i] : 0;
76 numerator[i] = GrandProdRelation::template compute_permutation_numerator<Accumulator>(evaluations,
78 denominator[i] = GrandProdRelation::template compute_permutation_denominator<Accumulator>(
79 evaluations, relation_parameters);
95 std::vector<FF> partial_numerators(num_threads);
96 std::vector<FF> partial_denominators(num_threads);
98 parallel_for(num_threads, [&](
size_t thread_idx) {
99 const size_t start = thread_idx * block_size;
100 const size_t end = (thread_idx + 1) * block_size;
101 for (
size_t i = start; i < end - 1; ++i) {
102 numerator[i + 1] *= numerator[i];
103 denominator[i + 1] *= denominator[i];
105 partial_numerators[thread_idx] = numerator[end - 1];
106 partial_denominators[thread_idx] = denominator[end - 1];
109 parallel_for(num_threads, [&](
size_t thread_idx) {
110 const size_t start = thread_idx * block_size;
111 const size_t end = (thread_idx + 1) * block_size;
112 if (thread_idx > 0) {
113 FF numerator_scaling = 1;
114 FF denominator_scaling = 1;
116 for (
size_t j = 0; j < thread_idx; ++j) {
117 numerator_scaling *= partial_numerators[j];
118 denominator_scaling *= partial_denominators[j];
120 for (
size_t i = start; i < end; ++i) {
121 numerator[i] *= numerator_scaling;
122 denominator[i] *= denominator_scaling;
127 FF::batch_invert(std::span{ &denominator[start], block_size });
131 auto& grand_product_polynomial = GrandProdRelation::get_grand_product_polynomial(full_polynomials);
132 grand_product_polynomial[0] = 0;
133 parallel_for(num_threads, [&](
size_t thread_idx) {
134 const size_t start = thread_idx * block_size;
135 const size_t end = (thread_idx == num_threads - 1) ? circuit_size - 1 : (thread_idx + 1) * block_size;
136 for (
size_t i = start; i < end; ++i) {
137 grand_product_polynomial[i + 1] = numerator[i] * denominator[i];
142template <
typename Flavor>
143void compute_permutation_grand_products(std::shared_ptr<typename Flavor::ProvingKey>& key,
147 using GrandProductRelations =
typename Flavor::GrandProductRelations;
148 using FF =
typename Flavor::FF;
150 constexpr size_t NUM_RELATIONS = std::tuple_size<GrandProductRelations>{};
151 barretenberg::constexpr_for<0, NUM_RELATIONS, 1>([&]<
size_t i>() {
152 using PermutationRelation =
typename std::tuple_element<i, GrandProductRelations>::type;
158 PermutationRelation::get_grand_product_polynomial(full_polynomials);
160 full_polynomial = key_polynomial.
share();
162 compute_permutation_grand_product<Flavor, PermutationRelation>(
163 key->circuit_size, full_polynomials, relation_parameters);
165 PermutationRelation::get_shifted_grand_product_polynomial(full_polynomials);
166 full_polynomial_shift = key_polynomial.
shifted();
187template <
typename Flavor,
typename StorageHandle>
void compute_concatenated_polynomials(StorageHandle* proving_key)
190 auto concatenation_groups = proving_key->get_concatenation_groups();
193 auto targets = proving_key->get_concatenated_constraints();
198 auto ordering_function = [&](
size_t i) {
199 auto my_group = concatenation_groups[i];
200 auto& current_target = targets[i];
203 for (
size_t j = 0; j < my_group.size(); j++) {
204 auto starting_write_offset = current_target.begin();
205 auto finishing_read_offset = my_group[j].begin();
206 std::advance(starting_write_offset, j * Flavor::MINI_CIRCUIT_SIZE);
207 std::advance(finishing_read_offset, Flavor::MINI_CIRCUIT_SIZE);
209 std::copy(my_group[j].begin(), finishing_read_offset, starting_write_offset);
212 parallel_for(concatenation_groups.size(), ordering_function);
237template <
typename Flavor,
typename StorageHandle>
238void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandle* proving_key)
241 using FF =
typename Flavor::FF;
244 constexpr auto sort_step = Flavor::SORT_STEP;
245 constexpr auto num_concatenated_wires = Flavor::NUM_CONCATENATED_WIRES;
246 constexpr auto full_circuit_size = Flavor::FULL_CIRCUIT_SIZE;
247 constexpr auto mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE;
250 constexpr uint32_t max_value = (1 << Flavor::MICRO_LIMB_BITS) - 1;
253 constexpr size_t sorted_elements_count = (max_value / sort_step) + 1 + (max_value % sort_step == 0 ? 0 : 1);
256 static_assert((num_concatenated_wires + 1) * sorted_elements_count < full_circuit_size);
259 std::vector<size_t> sorted_elements(sorted_elements_count);
262 sorted_elements[0] = max_value;
263 for (
size_t i = 1; i < sorted_elements_count; i++) {
264 sorted_elements[i] = (sorted_elements_count - 1 - i) * sort_step;
267 std::vector<std::vector<uint32_t>> ordered_vectors_uint(num_concatenated_wires);
268 auto ordered_constraint_polynomials = std::vector{ &proving_key->ordered_range_constraints_0,
269 &proving_key->ordered_range_constraints_1,
270 &proving_key->ordered_range_constraints_2,
271 &proving_key->ordered_range_constraints_3 };
272 std::vector<size_t> extra_denominator_uint(full_circuit_size);
275 auto concatenation_groups = proving_key->get_concatenation_groups();
279 auto ordering_function = [&](
size_t i) {
281 auto my_group = concatenation_groups[i];
282 auto& current_vector = ordered_vectors_uint[i];
283 current_vector.resize(Flavor::FULL_CIRCUIT_SIZE);
286 auto free_space_before_runway = full_circuit_size - sorted_elements_count;
289 size_t extra_denominator_offset = i * sorted_elements_count;
292 for (
size_t j = 0; j < Flavor::CONCATENATION_INDEX; j++) {
295 auto current_offset = j * mini_circuit_size;
297 for (
size_t k = 0; k < mini_circuit_size; k++) {
300 if ((current_offset + k) < free_space_before_runway) {
301 current_vector[current_offset + k] =
static_cast<uint32_t
>(
uint256_t(my_group[j][k]).data[0]);
305 extra_denominator_uint[extra_denominator_offset] =
306 static_cast<uint32_t
>(
uint256_t(my_group[j][k]).data[0]);
307 extra_denominator_offset++;
312 auto starting_write_offset = current_vector.begin();
313 std::advance(starting_write_offset, free_space_before_runway);
314 std::copy(sorted_elements.cbegin(), sorted_elements.cend(), starting_write_offset);
320 std::sort(current_vector.begin(), current_vector.end());
323 std::transform(current_vector.cbegin(),
324 current_vector.cend(),
325 (*ordered_constraint_polynomials[i]).begin(),
326 [](uint32_t in) { return FF(in); });
330 parallel_for(num_concatenated_wires, ordering_function);
331 ordered_vectors_uint.clear();
333 auto sorted_element_insertion_offset = extra_denominator_uint.begin();
334 std::advance(sorted_element_insertion_offset, num_concatenated_wires * sorted_elements_count);
337 std::copy(sorted_elements.cbegin(), sorted_elements.cend(), sorted_element_insertion_offset);
341 std::sort(extra_denominator_uint.begin(), extra_denominator_uint.end());
343 std::sort(std::execution::par_unseq, extra_denominator_uint.begin(), extra_denominator.end());
347 std::transform(extra_denominator_uint.cbegin(),
348 extra_denominator_uint.cend(),
349 proving_key->ordered_range_constraints_4.begin(),
350 [](uint32_t in) { return FF(in); });
368template <
typename Flavor>
inline void compute_extra_range_constraint_numerator(
auto proving_key)
372 auto full_circuit_size = Flavor::FULL_CIRCUIT_SIZE;
373 auto sort_step = Flavor::SORT_STEP;
374 auto num_concatenated_wires = Flavor::NUM_CONCATENATED_WIRES;
376 auto& extra_range_constraint_numerator = proving_key->ordered_extra_range_constraints_numerator;
378 uint32_t MAX_VALUE = (1 << Flavor::MICRO_LIMB_BITS) - 1;
381 size_t sorted_elements_count = (MAX_VALUE / sort_step) + 1 + (MAX_VALUE % sort_step == 0 ? 0 : 1);
384 ASSERT((num_concatenated_wires + 1) * sorted_elements_count < full_circuit_size);
386 std::vector<size_t> sorted_elements(sorted_elements_count);
389 sorted_elements[0] = MAX_VALUE;
390 for (
size_t i = 1; i < sorted_elements_count; i++) {
391 sorted_elements[i] = (sorted_elements_count - 1 - i) * sort_step;
395 auto fill_with_shift = [&](
size_t shift) {
396 for (
size_t i = 0; i < sorted_elements_count; i++) {
397 extra_range_constraint_numerator[shift + i * (num_concatenated_wires + 1)] = sorted_elements[i];
401 parallel_for(num_concatenated_wires + 1, fill_with_shift);
409template <
typename Flavor>
inline void compute_lagrange_polynomials_for_goblin_translator(
auto proving_key)
412 const size_t n = proving_key->circuit_size;
418 for (
size_t i = 1; i < Flavor::MINI_CIRCUIT_SIZE - 1; i += 2) {
419 lagrange_polynomial_odd_in_minicircuit[i] = 1;
420 lagrange_polynomial_even_in_minicircut[i + 1] = 1;
422 proving_key->lagrange_odd_in_minicircuit = lagrange_polynomial_odd_in_minicircuit.share();
424 proving_key->lagrange_even_in_minicircuit = lagrange_polynomial_even_in_minicircut.share();
425 lagrange_polynomial_second[1] = 1;
426 lagrange_polynomial_second_to_last_in_minicircuit[Flavor::MINI_CIRCUIT_SIZE - 2] = 1;
427 proving_key->lagrange_second_to_last_in_minicircuit = lagrange_polynomial_second_to_last_in_minicircuit.share();
428 proving_key->lagrange_second = lagrange_polynomial_second.share();
Definition: polynomial.hpp:12
Polynomial shifted() const
Returns an std::span of the left-shift of self.
Definition: polynomial.cpp:323
Polynomial share() const
Definition: polynomial.cpp:141
Definition: uint256.hpp:25
Definition: AvmMini_flavor.hpp:254
A container for the prover polynomials handles.
Definition: AvmMini_flavor.hpp:263
Definition: zip_view.hpp:159
Container for parameters used by the grand product (permutation, lookup) Honk relations.
Definition: relation_parameters.hpp:12