43 constexpr size_t READ_TERMS = Relation::READ_TERMS;
44 constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS;
46 auto& inverse_polynomial = Relation::get_inverse_polynomial(polynomials);
47 const size_t offset = inverse_polynomial.start_index();
48 const auto compute_inverses = [&](
size_t start,
size_t end) {
49 for (
size_t i = start; i < end; ++i) {
51 auto row = polynomials.get_row(i +
offset);
52 bool has_inverse = Relation::operation_exists_at_row(row);
57 bb::constexpr_for<0, READ_TERMS, 1>([&]<
size_t read_index> {
58 auto denominator_term =
59 Relation::template compute_read_term<Accumulator, read_index>(row, relation_parameters);
60 denominator *= denominator_term;
62 bb::constexpr_for<0, WRITE_TERMS, 1>([&]<
size_t write_index> {
63 auto denominator_term =
64 Relation::template compute_write_term<Accumulator, write_index>(row, relation_parameters);
65 denominator *= denominator_term;
67 inverse_polynomial.at(i) = denominator;
69 FF* ffstart = &inverse_polynomial.coeffs()[start];
75 if constexpr (UseMultithreading) {
76 const size_t min_iterations_per_thread = 128;
78 const size_t rows_per_thread = inverse_polynomial.size() / num_threads;
80 const size_t start = thread_idx * rows_per_thread;
81 const size_t end = (thread_idx == num_threads - 1) ? circuit_size : (thread_idx + 1) * rows_per_thread;
82 compute_inverses(start, end);
86 compute_inverses(0, inverse_polynomial.size());
120 const AllEntities& in,
121 const Parameters& params,
122 const FF& scaling_factor)
124 constexpr size_t READ_TERMS = Relation::READ_TERMS;
125 constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS;
128 using View =
typename Accumulator::View;
130 auto lookup_inverses = View(Relation::get_inverse_polynomial(in));
132 constexpr size_t NUM_TOTAL_TERMS = READ_TERMS + WRITE_TERMS;
142 bb::constexpr_for<0, READ_TERMS, 1>(
143 [&]<
size_t i>() { lookup_terms[i] = Relation::template compute_read_term<Accumulator, i>(in, params); });
144 bb::constexpr_for<0, WRITE_TERMS, 1>([&]<
size_t i>() {
145 lookup_terms[i + READ_TERMS] = Relation::template compute_write_term<Accumulator, i>(in, params);
148 bb::constexpr_for<0, NUM_TOTAL_TERMS, 1>([&]<
size_t i>() { denominator_accumulator[i] = lookup_terms[i]; });
151 [&]<
size_t i>() { denominator_accumulator[i + 1] *= denominator_accumulator[i]; });
153 auto inverse_accumulator = Accumulator(lookup_inverses);
155 const auto inverse_exists = Relation::template compute_inverse_exists<Accumulator>(in);
159 (denominator_accumulator[NUM_TOTAL_TERMS - 1] * lookup_inverses - inverse_exists) * scaling_factor;
162 for (
size_t i = 0; i < NUM_TOTAL_TERMS - 1; ++i) {
163 denominator_accumulator[NUM_TOTAL_TERMS - 1 - i] =
164 denominator_accumulator[NUM_TOTAL_TERMS - 2 - i] * inverse_accumulator;
165 inverse_accumulator = inverse_accumulator * lookup_terms[NUM_TOTAL_TERMS - 1 - i];
167 denominator_accumulator[0] = inverse_accumulator;
171 bb::constexpr_for<0, READ_TERMS, 1>([&]<
size_t i>() {
173 Relation::template compute_read_term_predicate<Accumulator, i>(in) * denominator_accumulator[i];
178 bb::constexpr_for<0, WRITE_TERMS, 1>([&]<
size_t i>() {
179 const auto p = Relation::template compute_write_term_predicate<Accumulator, i>(in);
180 const auto lookup_read_count = Relation::template lookup_read_counts<Accumulator, i>(in);
181 std::get<1>(accumulator) -= p * (denominator_accumulator[i + READ_TERMS] * lookup_read_count);
216 const AllEntities& in,
217 const Parameters& params,
218 const FF& scaling_factor)
220 constexpr size_t READ_TERMS = Relation::READ_TERMS;
221 constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS;
224 static_assert(READ_TERMS == 1);
225 static_assert(WRITE_TERMS == 1);
228 using View =
typename Accumulator::View;
230 auto permutation_inverses = View(Relation::get_inverse_polynomial(in));
232 constexpr size_t NUM_TOTAL_TERMS = 2;
242 permutation_terms[0] = Relation::template compute_read_term<Accumulator, 0>(in, params);
243 permutation_terms[1] = Relation::template compute_write_term<Accumulator, 0>(in, params);
245 bb::constexpr_for<0, NUM_TOTAL_TERMS, 1>([&]<
size_t i>() { denominator_accumulator[i] = permutation_terms[i]; });
248 [&]<
size_t i>() { denominator_accumulator[i + 1] *= denominator_accumulator[i]; });
250 auto inverse_accumulator = Accumulator(permutation_inverses);
252 const auto inverse_exists = Relation::template compute_inverse_exists<Accumulator>(in);
256 (denominator_accumulator[NUM_TOTAL_TERMS - 1] * permutation_inverses - inverse_exists) * scaling_factor;
259 for (
size_t i = 0; i < NUM_TOTAL_TERMS - 1; ++i) {
260 denominator_accumulator[NUM_TOTAL_TERMS - 1 - i] =
261 denominator_accumulator[NUM_TOTAL_TERMS - 2 - i] * inverse_accumulator;
262 inverse_accumulator = inverse_accumulator * permutation_terms[NUM_TOTAL_TERMS - 1 - i];
264 denominator_accumulator[0] = inverse_accumulator;
269 Relation::template compute_read_term_predicate<Accumulator, 0>(in) * denominator_accumulator[0];
274 Relation::template compute_write_term_predicate<Accumulator, 0>(in) * denominator_accumulator[1];
void accumulate_logderivative_lookup_subrelation_contributions(ContainerOverSubrelations &accumulator, const AllEntities &in, const Parameters ¶ms, const FF &scaling_factor)
Compute generic log-derivative lookup subrelation accumulation.
void compute_logderivative_inverse(Polynomials &polynomials, auto &relation_parameters, const size_t circuit_size)
Compute the inverse polynomial I(X) required for logderivative lookupsdetails Inverse may be defined ...
void accumulate_logderivative_permutation_subrelation_contributions(ContainerOverSubrelations &accumulator, const AllEntities &in, const Parameters ¶ms, const FF &scaling_factor)
Compute generic log-derivative set permutation subrelation accumulation.
size_t calculate_num_threads_pow2(size_t num_iterations, size_t min_iterations_per_thread)
calculates number of threads to create based on minimum iterations per thread, guaranteed power of 2