From b1c51ff9fdbb404afdfb23d1559dbdb6abd4d128 Mon Sep 17 00:00:00 2001 From: fcarreiro Date: Wed, 12 Feb 2025 16:13:43 +0000 Subject: [PATCH] interaction testing --- .../barretenberg/relations/relation_types.hpp | 6 +- .../barretenberg/vm2/common/stats.test.cpp | 3 + .../vm2/constraining/polynomials.cpp | 93 +++++++++++++ .../vm2/constraining/polynomials.hpp | 11 ++ .../constraining/relations/execution.test.cpp | 20 ++- .../constraining/testing/check_relation.cpp | 20 +++ .../constraining/testing/check_relation.hpp | 65 ++++++++- .../relations/lookups_bc_decomposition.hpp | 26 +++- .../generated/relations/lookups_bitwise.hpp | 25 +++- .../generated/relations/lookups_execution.hpp | 24 +++- .../relations/lookups_range_check.hpp | 128 +++++++++++++++--- .../generated/relations/lookups_sha256.hpp | 13 +- .../generated/relations/perms_execution.hpp | 12 +- .../src/barretenberg/vm2/proving_helper.cpp | 86 +----------- .../vm2/tracegen/lib/interaction_builder.hpp | 10 ++ .../vm2/tracegen/lib/lookup_builder.hpp | 18 +-- .../vm2/tracegen/lib/permutation_builder.hpp | 25 +--- .../vm2/tracegen/test_trace_container.cpp | 8 ++ .../vm2/tracegen/test_trace_container.hpp | 2 + .../vm2/tracegen/trace_container.cpp | 7 +- .../vm2/tracegen/trace_container.hpp | 4 +- .../bb-pil-backend/templates/lookup.hpp.hbs | 11 +- .../templates/permutation.hpp.hbs | 12 +- 23 files changed, 460 insertions(+), 169 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/vm2/common/stats.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm2/constraining/polynomials.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm2/constraining/polynomials.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm2/constraining/testing/check_relation.cpp diff --git a/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp b/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp index d340223077d2..795f0a729bdc 100644 --- a/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp @@ -21,10 +21,10 @@ namespace bb { template using GetParameterView = std::conditional_t, typename Params::DataType, View>; -template +template concept HasSubrelationLinearlyIndependentMember = requires(T) { { - std::get(T::SUBRELATION_LINEARLY_INDEPENDENT) + std::get<0>(T::SUBRELATION_LINEARLY_INDEPENDENT) } -> std::convertible_to; }; @@ -41,7 +41,7 @@ concept HasParameterLengthAdjustmentsMember = requires { T::TOTAL_LENGTH_ADJUSTM */ template constexpr bool subrelation_is_linearly_independent() { - if constexpr (HasSubrelationLinearlyIndependentMember) { + if constexpr (HasSubrelationLinearlyIndependentMember) { return std::get(Relation::SUBRELATION_LINEARLY_INDEPENDENT); } else { return true; diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/stats.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/common/stats.test.cpp new file mode 100644 index 000000000000..4476e03ad4bb --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/common/stats.test.cpp @@ -0,0 +1,3 @@ +// This is a hack needed to be able to use files that use stats (e.g., constraining/polynomials.cpp) in testing in vm2 +// It can be removed once VM1 is removed and stats are moved to VM2. +#include "barretenberg/vm/stats.cpp" \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/polynomials.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/polynomials.cpp new file mode 100644 index 000000000000..6dfa3753cc74 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/polynomials.cpp @@ -0,0 +1,93 @@ +#include "barretenberg/vm2/constraining/polynomials.hpp" + +#include + +#include "barretenberg/common/thread.hpp" +#include "barretenberg/vm/stats.hpp" +#include "barretenberg/vm2/common/constants.hpp" +#include "barretenberg/vm2/generated/columns.hpp" + +namespace bb::avm2::constraining { + +AvmProver::ProverPolynomials compute_polynomials(tracegen::TraceContainer& trace) +{ + AvmProver::ProverPolynomials polys; + + // Polynomials that will be shifted need special care. + AVM_TRACK_TIME("proving/init_polys_to_be_shifted", ({ + auto to_be_shifted = polys.get_to_be_shifted(); + + // TODO: cannot parallelize because Polynomial construction uses parallelism. + for (size_t i = 0; i < to_be_shifted.size(); i++) { + auto& poly = to_be_shifted[i]; + // WARNING! Column-Polynomials order matters! + Column col = static_cast(TO_BE_SHIFTED_COLUMNS_ARRAY.at(i)); + // We need at least 2 rows for the shifted columns. + uint32_t num_rows = std::max(trace.get_column_rows(col), 2); + + poly = AvmProver::Polynomial( + /*memory size*/ + num_rows - 1, + /*largest possible index*/ CIRCUIT_SUBGROUP_SIZE, + /*make shiftable with offset*/ 1); + } + })); + + // Catch-all with fully formed polynomials + // Note: derived polynomials (i.e., inverses) are not in the trace at this point, because they can only + // be computed after committing to the other witnesses. Therefore, they will be initialized as empty + // and they will be not set below. The derived polynomials will be reinitialized and set in the prover + // itself mid-proving. (TO BE DONE!). + // + // NOTE FOR SELF: however, the counts will be known here and the inv have the same size? + // think about it and check the formula. + AVM_TRACK_TIME("proving/init_polys_unshifted", ({ + auto unshifted = polys.get_unshifted(); + + // Derived polynomials will be empty. + bb::parallel_for(unshifted.size(), [&](size_t i) { + auto& poly = unshifted[i]; + // FIXME: this is a bad way to check if the polynomial is already initialized. + // It could be that it has been initialized, but it's all zeroes. + if (!poly.is_empty()) { + // Already initialized above. + return; + } + + // WARNING! Column-Polynomials order matters! + Column col = static_cast(i); + const auto num_rows = trace.get_column_rows(col); + poly = AvmProver::Polynomial::create_non_parallel_zero_init(num_rows, CIRCUIT_SUBGROUP_SIZE); + }); + })); + + AVM_TRACK_TIME("proving/set_polys_unshifted", ({ + auto unshifted = polys.get_unshifted(); + + // TODO: We are now visiting per-column. Profile if per-row is better. + // This would need changes to the trace container. + bb::parallel_for(unshifted.size(), [&](size_t i) { + // WARNING! Column-Polynomials order matters! + auto& poly = unshifted[i]; + Column col = static_cast(i); + + trace.visit_column(col, [&](size_t row, const AvmProver::FF& value) { + // We use `at` because we are sure the row exists and the value is non-zero. + poly.at(row) = value; + }); + // We free columns as we go. + // TODO: If we merge the init with the setting, this would be even more memory efficient. + trace.clear_column(col); + }); + })); + + AVM_TRACK_TIME("proving/set_polys_shifted", ({ + for (auto [shifted, to_be_shifted] : zip_view(polys.get_shifted(), polys.get_to_be_shifted())) { + shifted = to_be_shifted.shifted(); + } + })); + + return polys; +} + +} // namespace bb::avm2::constraining \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/polynomials.hpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/polynomials.hpp new file mode 100644 index 000000000000..3ea0b0d5902f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/polynomials.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "barretenberg/vm2/generated/prover.hpp" +#include "barretenberg/vm2/tracegen/trace_container.hpp" + +namespace bb::avm2::constraining { + +// Computes the polynomials from the trace, and destroys it in the process. +AvmProver::ProverPolynomials compute_polynomials(tracegen::TraceContainer& trace); + +} // namespace bb::avm2::constraining \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/execution.test.cpp index 11c8d42f220d..1b9b98214a91 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/relations/execution.test.cpp @@ -6,7 +6,10 @@ #include "barretenberg/vm2/constraining/testing/check_relation.hpp" #include "barretenberg/vm2/generated/flavor_settings.hpp" #include "barretenberg/vm2/generated/relations/execution.hpp" +#include "barretenberg/vm2/generated/relations/lookups_execution.hpp" +#include "barretenberg/vm2/generated/relations/perms_execution.hpp" #include "barretenberg/vm2/testing/macros.hpp" +#include "barretenberg/vm2/tracegen/lib/permutation_builder.hpp" #include "barretenberg/vm2/tracegen/test_trace_container.hpp" namespace bb::avm2::constraining { @@ -16,19 +19,34 @@ using tracegen::TestTraceContainer; using FF = AvmFlavorSettings::FF; using C = Column; using execution = bb::avm2::execution; +using perm_dummy_dynamic_relation = perm_dummy_dynamic_relation; TEST(ExecutionConstrainingTest, Basic) { // clang-format off TestTraceContainer trace({ {{ C::execution_sel, 1 }, {C::execution_clk, 0}, { C::execution_pc, 0 }}, - {{ C::execution_sel, 1 }, {C::execution_clk, 1}, { C::execution_pc, 20 }, { C::execution_last, 1 }} + {{ C::execution_sel, 1 }, {C::execution_clk, 1}, { C::execution_pc, 20 }, { C::execution_last, 1 }} }); // clang-format on check_relation(trace); } +// This is just a PoC. +TEST(ExecutionConstrainingTest, Permutation) +{ + // clang-format off + TestTraceContainer trace({ + {{ C::precomputed_first_row, 1 }}, + {{ C::execution_sel, 1 }, {C::execution_op1, 1}, {C::execution_op2, 2}, {C::execution_op3, 3}, {C::execution_op4, 4}} + }); + // clang-format on + + tracegen::PermutationBuilder().process(trace); + check_interaction(trace); +} + TEST(ExecutionConstrainingTest, Continuity) { // clang-format off diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/testing/check_relation.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/testing/check_relation.cpp new file mode 100644 index 000000000000..961e1db7fdf0 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/testing/check_relation.cpp @@ -0,0 +1,20 @@ +#include "barretenberg/vm2/constraining/testing/check_relation.hpp" + +namespace bb::avm2::constraining::detail { + +const RelationParameters& get_test_params() +{ + static RelationParameters params = { + .eta = 0, + .beta = FF::random_element(), + .gamma = FF::random_element(), + .public_input_delta = 0, + .lookup_grand_product_delta = 0, + .beta_sqr = 0, + .beta_cube = 0, + .eccvm_set_permutation_delta = 0, + }; + return params; +} + +} // namespace bb::avm2::constraining::detail \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/testing/check_relation.hpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/testing/check_relation.hpp index 8d8f67b524f5..0ccca00153ae 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/testing/check_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/testing/check_relation.hpp @@ -1,23 +1,42 @@ #pragma once #include +#include #include #include #include "barretenberg/common/log.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/relations/relation_types.hpp" +#include "barretenberg/vm2/constraining/polynomials.hpp" #include "barretenberg/vm2/tracegen/test_trace_container.hpp" namespace bb::avm2::constraining { +namespace detail { -template -void check_relation_internal(const Trace& trace, std::span subrelations) +const RelationParameters& get_test_params(); + +template constexpr bool subrelation_is_linearly_independent(size_t subrelation_index) +{ + if constexpr (HasSubrelationLinearlyIndependentMember) { + return Relation::SUBRELATION_LINEARLY_INDEPENDENT[subrelation_index]; + } else { + return true; + } +} + +template +void check_relation_internal(const Trace& trace, std::span subrelations, RowGetter get_row) { typename Relation::SumcheckArrayOfValuesOverSubrelations result{}; + // Accumulate the trace over the subrelations and check the result + // if the subrelation is linearly independent. for (size_t r = 0; r < trace.size(); ++r) { - Relation::accumulate(result, trace.at(r), {}, 1); + Relation::accumulate(result, get_row(trace, r), get_test_params(), 1); for (size_t j : subrelations) { - if (!result[j].is_zero()) { + if (subrelation_is_linearly_independent(j) && !result[j].is_zero()) { throw std::runtime_error(format("Relation ", Relation::NAME, ", subrelation ", @@ -27,13 +46,26 @@ void check_relation_internal(const Trace& trace, std::span subrelations) } } } + // For all subrelations, the result should be zero at the end of the trace. + for (size_t j : subrelations) { + if (!result[j].is_zero()) { + throw std::runtime_error(format("Relation ", + Relation::NAME, + ", subrelation ", + Relation::get_subrelation_label(j), + " is non-zero at end of trace")); + } + } } +} // namespace detail + template void check_relation(const tracegen::TestTraceContainer& trace, Ts... subrelation) { std::array subrelations = { subrelation... }; - check_relation_internal(trace.as_rows(), subrelations); + detail::check_relation_internal( + trace.as_rows(), subrelations, [](const auto& trace, size_t r) { return trace.at(r); }); } template void check_relation(const tracegen::TestTraceContainer& trace) @@ -42,4 +74,27 @@ template void check_relation(const tracegen::TestTraceContai [&](std::index_sequence) { check_relation(trace, Is...); }(subrelations); } +// Computes logderiv inverses and checks the lookup or permutation. +template void check_interaction(const tracegen::TestTraceContainer& trace) +{ + using Settings = typename Lookup::Settings; + if (trace.get_column_rows(Settings::INVERSES) == 0) { + std::cerr << "Inverses for " << Lookup::NAME + << " are unset. Did you forget to run a lookup/permutation builder?" << std::endl; + abort(); + } + // We copy the trace because constructing the polynomials destroys it. + auto trace_copy = trace; + const auto num_rows = trace.get_num_rows(); + // We compute the polys and the real inverses. + auto polys = constraining::compute_polynomials(trace_copy); + bb::compute_logderivative_inverse(polys, detail::get_test_params(), num_rows); + // Finally we check the interaction. + [&](std::index_sequence) { + constexpr std::array subrels = { Is... }; + detail::check_relation_internal( + polys, subrels, [](const auto& polys, size_t r) { return polys.get_row(r); }); + }(std::make_index_sequence()); +} + } // namespace bb::avm2::constraining \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bc_decomposition.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bc_decomposition.hpp index e6f6d10664ad..1ecaee46dd27 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bc_decomposition.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bc_decomposition.hpp @@ -72,15 +72,24 @@ template class lookup_bytecode_bytes_are_bytes_relation : public GenericLookupRelation { public: + using Settings = lookup_bytecode_bytes_are_bytes_lookup_settings; static constexpr std::string_view NAME = lookup_bytecode_bytes_are_bytes_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.bc_decomposition_sel.is_zero() && in.precomputed_sel_range_8.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_bytecode_bytes_are_bytes = GenericLookup; /////////////////// lookup_bytecode_to_read_unary /////////////////// @@ -149,14 +158,23 @@ template class lookup_bytecode_to_read_unary_relation : public GenericLookupRelation { public: + using Settings = lookup_bytecode_to_read_unary_lookup_settings; static constexpr std::string_view NAME = lookup_bytecode_to_read_unary_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.bc_decomposition_sel.is_zero() && in.precomputed_sel_unary.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_bytecode_to_read_unary = GenericLookup; } // namespace bb::avm2 \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bitwise.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bitwise.hpp index 7e5e9f8c932d..d66d77c866f1 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bitwise.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bitwise.hpp @@ -74,14 +74,24 @@ class lookup_bitw_byte_lengths_lookup_settings { template class lookup_bitw_byte_lengths_relation : public GenericLookupRelation { public: + using Settings = lookup_bitw_byte_lengths_lookup_settings; static constexpr std::string_view NAME = lookup_bitw_byte_lengths_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.bitwise_start.is_zero() && in.precomputed_sel_integral_tag.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template using lookup_bitw_byte_lengths = GenericLookup; /////////////////// lookup_bitw_byte_operations /////////////////// @@ -156,14 +166,23 @@ template class lookup_bitw_byte_operations_relation : public GenericLookupRelation { public: + using Settings = lookup_bitw_byte_operations_lookup_settings; static constexpr std::string_view NAME = lookup_bitw_byte_operations_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.bitwise_sel.is_zero() && in.precomputed_sel_bitwise.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_bitw_byte_operations = GenericLookup; } // namespace bb::avm2 \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_execution.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_execution.hpp index cc655d526869..871b3ec711ee 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_execution.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_execution.hpp @@ -82,14 +82,24 @@ class lookup_dummy_precomputed_lookup_settings { template class lookup_dummy_precomputed_relation : public GenericLookupRelation { public: + using Settings = lookup_dummy_precomputed_lookup_settings; static constexpr std::string_view NAME = lookup_dummy_precomputed_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.execution_sel.is_zero() && in.precomputed_sel_bitwise.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template using lookup_dummy_precomputed = GenericLookup; /////////////////// lookup_dummy_dynamic /////////////////// @@ -162,13 +172,23 @@ class lookup_dummy_dynamic_lookup_settings { template class lookup_dummy_dynamic_relation : public GenericLookupRelation { public: + using Settings = lookup_dummy_dynamic_lookup_settings; static constexpr std::string_view NAME = lookup_dummy_dynamic_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.execution_sel.is_zero() && in.execution_sel.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template using lookup_dummy_dynamic = GenericLookup; } // namespace bb::avm2 \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_range_check.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_range_check.hpp index 5a4dbb8c534d..778fa1f20d46 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_range_check.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_range_check.hpp @@ -75,14 +75,24 @@ class lookup_rng_chk_pow_2_lookup_settings { template class lookup_rng_chk_pow_2_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_pow_2_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_pow_2_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel.is_zero() && in.precomputed_sel_range_8.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template using lookup_rng_chk_pow_2 = GenericLookup; /////////////////// lookup_rng_chk_diff /////////////////// @@ -145,14 +155,24 @@ class lookup_rng_chk_diff_lookup_settings { template class lookup_rng_chk_diff_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_diff_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_diff_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel.is_zero() && in.precomputed_sel_range_16.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template using lookup_rng_chk_diff = GenericLookup; /////////////////// lookup_rng_chk_is_r0_16_bit /////////////////// @@ -216,15 +236,24 @@ template class lookup_rng_chk_is_r0_16_bit_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_is_r0_16_bit_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_is_r0_16_bit_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel_r0_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_rng_chk_is_r0_16_bit = GenericLookup; /////////////////// lookup_rng_chk_is_r1_16_bit /////////////////// @@ -288,15 +317,24 @@ template class lookup_rng_chk_is_r1_16_bit_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_is_r1_16_bit_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_is_r1_16_bit_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel_r1_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_rng_chk_is_r1_16_bit = GenericLookup; /////////////////// lookup_rng_chk_is_r2_16_bit /////////////////// @@ -360,15 +398,24 @@ template class lookup_rng_chk_is_r2_16_bit_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_is_r2_16_bit_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_is_r2_16_bit_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel_r2_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_rng_chk_is_r2_16_bit = GenericLookup; /////////////////// lookup_rng_chk_is_r3_16_bit /////////////////// @@ -432,15 +479,24 @@ template class lookup_rng_chk_is_r3_16_bit_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_is_r3_16_bit_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_is_r3_16_bit_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel_r3_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_rng_chk_is_r3_16_bit = GenericLookup; /////////////////// lookup_rng_chk_is_r4_16_bit /////////////////// @@ -504,15 +560,24 @@ template class lookup_rng_chk_is_r4_16_bit_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_is_r4_16_bit_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_is_r4_16_bit_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel_r4_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_rng_chk_is_r4_16_bit = GenericLookup; /////////////////// lookup_rng_chk_is_r5_16_bit /////////////////// @@ -576,15 +641,24 @@ template class lookup_rng_chk_is_r5_16_bit_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_is_r5_16_bit_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_is_r5_16_bit_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel_r5_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_rng_chk_is_r5_16_bit = GenericLookup; /////////////////// lookup_rng_chk_is_r6_16_bit /////////////////// @@ -648,15 +722,24 @@ template class lookup_rng_chk_is_r6_16_bit_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_is_r6_16_bit_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_is_r6_16_bit_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel_r6_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_rng_chk_is_r6_16_bit = GenericLookup; /////////////////// lookup_rng_chk_is_r7_16_bit /////////////////// @@ -720,14 +803,23 @@ template class lookup_rng_chk_is_r7_16_bit_relation : public GenericLookupRelation { public: + using Settings = lookup_rng_chk_is_r7_16_bit_lookup_settings; static constexpr std::string_view NAME = lookup_rng_chk_is_r7_16_bit_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.range_check_sel.is_zero() && in.precomputed_sel_range_16.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_rng_chk_is_r7_16_bit = GenericLookup; } // namespace bb::avm2 \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_sha256.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_sha256.hpp index 5d954b5305c7..61e05ab5ecce 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_sha256.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_sha256.hpp @@ -77,14 +77,23 @@ template class lookup_sha256_round_constant_relation : public GenericLookupRelation { public: + using Settings = lookup_sha256_round_constant_lookup_settings; static constexpr std::string_view NAME = lookup_sha256_round_constant_lookup_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.sha256_sel.is_zero() && in.precomputed_sel_sha256_compression.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template -using lookup_sha256_round_constant = GenericLookup; } // namespace bb::avm2 \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/perms_execution.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/perms_execution.hpp index 010245c343fa..d355a45a5cdf 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/perms_execution.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/perms_execution.hpp @@ -65,13 +65,23 @@ class perm_dummy_dynamic_permutation_settings { template class perm_dummy_dynamic_relation : public GenericPermutationRelation { public: + using Settings = perm_dummy_dynamic_permutation_settings; static constexpr std::string_view NAME = perm_dummy_dynamic_permutation_settings::NAME; template inline static bool skip(const AllEntities& in) { return in.execution_sel.is_zero() && in.execution_sel.is_zero(); } + + static std::string get_subrelation_label(size_t index) + { + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template using perm_dummy_dynamic = GenericPermutation; } // namespace bb::avm2 \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp b/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp index cddbb65eecd6..29480e6864fa 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp @@ -10,6 +10,7 @@ #include "barretenberg/vm/stats.hpp" #include "barretenberg/vm2/common/constants.hpp" #include "barretenberg/vm2/constraining/check_circuit.hpp" +#include "barretenberg/vm2/constraining/polynomials.hpp" #include "barretenberg/vm2/debugger.hpp" #include "barretenberg/vm2/generated/prover.hpp" #include "barretenberg/vm2/generated/verifier.hpp" @@ -33,92 +34,11 @@ std::shared_ptr create_proving_key(AvmProver::ProverPolyn return proving_key; } -AvmProver::ProverPolynomials compute_polynomials(tracegen::TraceContainer& trace) -{ - AvmProver::ProverPolynomials polys; - - // Polynomials that will be shifted need special care. - AVM_TRACK_TIME("proving/init_polys_to_be_shifted", ({ - auto to_be_shifted = polys.get_to_be_shifted(); - - // TODO: cannot parallelize because Polynomial construction uses parallelism. - for (size_t i = 0; i < to_be_shifted.size(); i++) { - auto& poly = to_be_shifted[i]; - // WARNING! Column-Polynomials order matters! - Column col = static_cast(TO_BE_SHIFTED_COLUMNS_ARRAY.at(i)); - // We need at least 2 rows for the shifted columns. - uint32_t num_rows = std::max(trace.get_column_rows(col), 2); - - poly = AvmProver::Polynomial( - /*memory size*/ - num_rows - 1, - /*largest possible index*/ CIRCUIT_SUBGROUP_SIZE, - /*make shiftable with offset*/ 1); - } - })); - - // Catch-all with fully formed polynomials - // Note: derived polynomials (i.e., inverses) are not in the trace at this point, because they can only - // be computed after committing to the other witnesses. Therefore, they will be initialized as empty - // and they will be not set below. The derived polynomials will be reinitialized and set in the prover - // itself mid-proving. (TO BE DONE!). - // - // NOTE FOR SELF: however, the counts will be known here and the inv have the same size? - // think about it and check the formula. - AVM_TRACK_TIME("proving/init_polys_unshifted", ({ - auto unshifted = polys.get_unshifted(); - - // Derived polynomials will be empty. - bb::parallel_for(unshifted.size(), [&](size_t i) { - auto& poly = unshifted[i]; - // FIXME: this is a bad way to check if the polynomial is already initialized. - // It could be that it has been initialized, but it's all zeroes. - if (!poly.is_empty()) { - // Already initialized above. - return; - } - - // WARNING! Column-Polynomials order matters! - Column col = static_cast(i); - const auto num_rows = trace.get_column_rows(col); - poly = AvmProver::Polynomial::create_non_parallel_zero_init(num_rows, CIRCUIT_SUBGROUP_SIZE); - }); - })); - - AVM_TRACK_TIME("proving/set_polys_unshifted", ({ - auto unshifted = polys.get_unshifted(); - - // TODO: We are now visiting per-column. Profile if per-row is better. - // This would need changes to the trace container. - bb::parallel_for(unshifted.size(), [&](size_t i) { - // WARNING! Column-Polynomials order matters! - auto& poly = unshifted[i]; - Column col = static_cast(i); - - trace.visit_column(col, [&](size_t row, const AvmProver::FF& value) { - // We use `at` because we are sure the row exists and the value is non-zero. - poly.at(row) = value; - }); - // We free columns as we go. - // TODO: If we merge the init with the setting, this would be even more memory efficient. - trace.clear_column(col); - }); - })); - - AVM_TRACK_TIME("proving/set_polys_shifted", ({ - for (auto [shifted, to_be_shifted] : zip_view(polys.get_shifted(), polys.get_to_be_shifted())) { - shifted = to_be_shifted.shifted(); - } - })); - - return polys; -} - } // namespace std::pair AvmProvingHelper::prove(tracegen::TraceContainer&& trace) { - auto polynomials = AVM_TRACK_TIME_V("proving/prove:compute_polynomials", compute_polynomials(trace)); + auto polynomials = AVM_TRACK_TIME_V("proving/prove:compute_polynomials", constraining::compute_polynomials(trace)); auto proving_key = AVM_TRACK_TIME_V("proving/prove:proving_key", create_proving_key(polynomials)); auto prover = AVM_TRACK_TIME_V("proving/prove:construct_prover", AvmProver(proving_key, proving_key->commitment_key)); @@ -147,7 +67,7 @@ bool AvmProvingHelper::check_circuit(tracegen::TraceContainer&& trace) } // Warning: this destroys the trace. - auto polynomials = AVM_TRACK_TIME_V("proving/prove:compute_polynomials", compute_polynomials(trace)); + auto polynomials = AVM_TRACK_TIME_V("proving/prove:compute_polynomials", constraining::compute_polynomials(trace)); try { AVM_TRACK_TIME("proving/check_circuit", constraining::run_check_circuit(polynomials, num_rows)); } catch (std::runtime_error& e) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/interaction_builder.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/interaction_builder.hpp index 3724b33cc182..08bc43a5a90c 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/interaction_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/interaction_builder.hpp @@ -10,4 +10,14 @@ class InteractionBuilderInterface { virtual void process(TraceContainer& trace) = 0; }; +// We set a dummy value in the inverse column so that the size of the column is right. +// The correct value will be set by the prover. +template void SetDummyInverses(TraceContainer& trace) +{ + trace.visit_column(LookupSettings::SRC_SELECTOR, + [&](uint32_t row, const FF&) { trace.set(LookupSettings::INVERSES, row, 0xdeadbeef); }); + trace.visit_column(LookupSettings::DST_SELECTOR, + [&](uint32_t row, const FF&) { trace.set(LookupSettings::INVERSES, row, 0xdeadbeef); }); +} + } // namespace bb::avm2::tracegen \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/lookup_builder.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/lookup_builder.hpp index 3c7f60d34ddc..5e221f5b58d6 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/lookup_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/lookup_builder.hpp @@ -34,16 +34,9 @@ template class BaseLookupTraceBuilder : public Intera auto src_values = trace.get_multiple(LookupSettings::SRC_COLUMNS, row); uint32_t dst_row = find_in_dst(src_values); // Assumes an efficient implementation. trace.set(LookupSettings::COUNTS, dst_row, trace.get(LookupSettings::COUNTS, dst_row) + 1); - - // We set a dummy value in the inverse column so that the size of the column is right. - // The correct value will be set by the prover. - trace.set(LookupSettings::INVERSES, row, 0xdeadbeef); }); - // We set a dummy value in the inverse column so that the size of the column is right. - // The correct value will be set by the prover. - trace.visit_column(LookupSettings::DST_SELECTOR, - [&](uint32_t row, const FF&) { trace.set(LookupSettings::INVERSES, row, 0xdeadbeef); }); + SetDummyInverses(trace); } protected: @@ -117,10 +110,6 @@ template class LookupIntoDynamicTableSequential : publ auto src_values = trace.get_multiple(LookupSettings::SRC_COLUMNS, row); - // We set a dummy value in the inverse column so that the size of the column is right. - // The correct value will be set by the prover. - trace.set(LookupSettings::INVERSES, row, 0xdeadbeef); - // We find the first row in the destination columns where the values match. while (dst_row < max_dst_row) { // TODO: As an optimization, we could try to only walk the rows where the selector is active. @@ -137,10 +126,7 @@ template class LookupIntoDynamicTableSequential : publ ". Could not find tuple in destination."); }); - // We set a dummy value in the inverse column so that the size of the column is right. - // The correct value will be set by the prover. - trace.visit_column(LookupSettings::DST_SELECTOR, - [&](uint32_t row, const FF&) { trace.set(LookupSettings::INVERSES, row, 0xdeadbeef); }); + SetDummyInverses(trace); } }; diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/permutation_builder.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/permutation_builder.hpp index a95e5c1e75ef..e62532752761 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/permutation_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/lib/permutation_builder.hpp @@ -1,12 +1,5 @@ #pragma once -#include -#include -#include - -#include "barretenberg/vm2/common/field.hpp" -#include "barretenberg/vm2/common/map.hpp" -#include "barretenberg/vm2/generated/columns.hpp" #include "barretenberg/vm2/tracegen/lib/interaction_builder.hpp" #include "barretenberg/vm2/tracegen/trace_container.hpp" @@ -17,23 +10,7 @@ namespace bb::avm2::tracegen { // and let the provers use it to more efficiently compute the inverses. template class PermutationBuilder : public InteractionBuilderInterface { public: - void process(TraceContainer& trace) override - { - // Let "src_sel {c1, c2, ...} is dst_sel {d1, d2, ...}" be a permutation. - trace.visit_column(PermutationSettings::SRC_SELECTOR, [&](uint32_t row, const FF& src_sel_value) { - assert(src_sel_value == 1); - (void)src_sel_value; // Avoid GCC complaining of unused parameter when asserts are disabled. - - // We set a dummy value in the inverse column so that the size of the column is right. - // The correct value will be set by the prover. - trace.set(PermutationSettings::INVERSES, row, 0xdeadbeef); - }); - - // We set a dummy value in the inverse column so that the size of the column is right. - // The correct value will be set by the prover. - trace.visit_column(PermutationSettings::DST_SELECTOR, - [&](uint32_t row, const FF&) { trace.set(PermutationSettings::INVERSES, row, 0xdeadbeef); }); - } + void process(TraceContainer& trace) override { SetDummyInverses(trace); } }; } // namespace bb::avm2::tracegen \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.cpp index 8e5caa93d4a6..e8b24d095e18 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.cpp @@ -5,6 +5,14 @@ namespace bb::avm2::tracegen { +TestTraceContainer::TestTraceContainer(const TestTraceContainer& other) +{ + for (size_t i = 0; i < num_columns(); ++i) { + const auto column = static_cast(i); + other.visit_column(column, [this, column](uint32_t row, const auto& value) { set(column, row, value); }); + } +} + TestTraceContainer TestTraceContainer::from_rows(const RowTraceContainer& rows) { TestTraceContainer container; diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.hpp index d6fa33157afd..409205de7f75 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/test_trace_container.hpp @@ -23,6 +23,8 @@ class TestTraceContainer : public TraceContainer { set(row, values[row]); } } + // Copy constructor. We allow copying for testing purposes. + TestTraceContainer(const TestTraceContainer&); // Returns a trace in dense format with properly filled in shifted columns. RowTraceContainer as_rows() const; diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.cpp index 76c9471120a6..7af0f0e83fec 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.cpp @@ -31,7 +31,7 @@ void TraceContainer::set(Column col, uint32_t row, const FF& value) std::unique_lock lock(column_data.mutex); if (!value.is_zero()) { column_data.rows.insert_or_assign(row, value); - column_data.max_row_number = std::max(column_data.max_row_number, row); + column_data.max_row_number = std::max(column_data.max_row_number, static_cast(row)); } else { auto num_erased = column_data.rows.erase(row); if (column_data.max_row_number == row && num_erased > 0) { @@ -64,10 +64,11 @@ uint32_t TraceContainer::get_column_rows(Column col) const // Trigger recalculation of max row number. auto keys = std::views::keys(column_data.rows); const auto it = std::max_element(keys.begin(), keys.end()); - column_data.max_row_number = it == keys.end() ? 0 : *it; + // We use -1 to indicate that the column is empty. + column_data.max_row_number = it == keys.end() ? -1 : static_cast(*it); column_data.row_number_dirty = false; } - return column_data.max_row_number + 1; + return static_cast(column_data.max_row_number + 1); } uint32_t TraceContainer::get_num_rows_without_clk() const diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.hpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.hpp index 8bd3029a220f..69e1f4b2c203 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/trace_container.hpp @@ -55,8 +55,8 @@ class TraceContainer { // Observe that therefore concurrent write access to different columns is cheap. struct SparseColumn { std::shared_mutex mutex; - uint32_t max_row_number = 0; - bool row_number_dirty; // needs recalculation + int64_t max_row_number = -1; // We use -1 to indicate that the column is empty. + bool row_number_dirty; // Needs recalculation. // Future memory optimization notes: we can do the same trick as in Operand. // That is, store a variant with a unique_ptr. However, we should benchmark this. // (see serialization.hpp). diff --git a/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs index ce3f02b73e5d..b98097272391 100644 --- a/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs @@ -85,6 +85,7 @@ class {{lookup_name}}_lookup_settings { template class {{lookup_name}}_relation : public GenericLookupRelation<{{lookup_name}}_lookup_settings, FF_> { public: + using Settings = {{lookup_name}}_lookup_settings; static constexpr std::string_view NAME = {{lookup_name}}_lookup_settings::NAME; {{! TODO: This is a safe skippable condition, but there might be a better one. --}} @@ -93,8 +94,16 @@ template class {{lookup_name}}_relation : public GenericLookupRel return in.{{lhs_selector}}.is_zero() && in.{{rhs_selector}}.is_zero(); } + static std::string get_subrelation_label(size_t index) { + {{! from generic_lookup_relation.hpp }} + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template using {{lookup_name}} = GenericLookup<{{lookup_name}}_lookup_settings, FF_>; {{/with}}{{/each}} } // namespace bb::{{snakeCase root_name}} \ No newline at end of file diff --git a/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs index d17ff0a58723..ab49cf214290 100644 --- a/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs @@ -51,6 +51,7 @@ class {{perm_name}}_permutation_settings { template class {{perm_name}}_relation : public GenericPermutationRelation<{{perm_name}}_permutation_settings, FF_> { public: + using Settings = {{perm_name}}_permutation_settings; static constexpr std::string_view NAME = {{perm_name}}_permutation_settings::NAME; {{! TODO: This is a safe skippable condition, but there might be a better one. --}} @@ -58,8 +59,17 @@ template class {{perm_name}}_relation : public GenericPermutation { return in.{{lhs_selector}}.is_zero() && in.{{rhs_selector}}.is_zero(); } + + static std::string get_subrelation_label(size_t index) { + {{! from generic_permutation_relation.hpp }} + if (index == 0) { + return "INVERSES_ARE_CORRECT"; + } else if (index == 1) { + return "ACCUMULATION_IS_CORRECT"; + } + return std::to_string(index); + } }; -template using {{perm_name}} = GenericPermutation<{{perm_name}}_permutation_settings, FF_>; {{/with}}{{/each}} } // namespace bb::{{snakeCase root_name}} \ No newline at end of file