Skip to content

Commit f4c31ed

Browse files
committed
feat(avm)!: support expressions in lookups (part 1)
1 parent 3ce88cc commit f4c31ed

File tree

62 files changed

+5282
-5287
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+5282
-5287
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#pragma once
2+
3+
#include "barretenberg/vm2/common/field.hpp"
4+
#include "barretenberg/vm2/generated/columns.hpp"
5+
6+
namespace bb::avm2 {
7+
8+
/**
9+
* @brief Relation expression representing a constant value.
10+
*/
11+
struct ConstantExpression {
12+
FF value;
13+
static constexpr bool __IS_EXPRESSION__ = true;
14+
15+
constexpr explicit ConstantExpression(FF value)
16+
: value(value)
17+
{}
18+
};
19+
20+
/**
21+
* @brief Relation expression representing a column.
22+
*/
23+
struct ColumnExpression {
24+
ColumnAndShifts column;
25+
static constexpr bool __IS_EXPRESSION__ = true;
26+
27+
constexpr explicit ColumnExpression(ColumnAndShifts column)
28+
: column(column)
29+
{}
30+
};
31+
32+
/**
33+
* @brief Relation expression representing a unary negation.
34+
*/
35+
template <typename InnerType> struct NegExpression {
36+
InnerType inner;
37+
static constexpr bool __IS_EXPRESSION__ = true;
38+
39+
constexpr explicit NegExpression(InnerType inner)
40+
: inner(std::forward<InnerType>(inner))
41+
{}
42+
};
43+
44+
/**
45+
* @brief Relation expression representing an addition.
46+
*/
47+
template <typename LhsType, typename RhsType> struct AddExpression {
48+
LhsType lhs;
49+
RhsType rhs;
50+
51+
constexpr explicit AddExpression(LhsType&& lhs, RhsType&& rhs)
52+
: lhs(std::forward<LhsType>(lhs))
53+
, rhs(std::forward<RhsType>(rhs))
54+
{}
55+
};
56+
57+
/**
58+
* @brief Relation expression representing a subtraction.
59+
*/
60+
template <typename LhsType, typename RhsType> struct SubExpression {
61+
LhsType lhs;
62+
RhsType rhs;
63+
static constexpr bool __IS_EXPRESSION__ = true;
64+
65+
constexpr explicit SubExpression(LhsType&& lhs, RhsType&& rhs)
66+
: lhs(std::forward<LhsType>(lhs))
67+
, rhs(std::forward<RhsType>(rhs))
68+
{}
69+
};
70+
71+
/**
72+
* @brief Relation expression representing a multiplication.
73+
*/
74+
template <typename LhsType, typename RhsType> struct MulExpression {
75+
LhsType lhs;
76+
RhsType rhs;
77+
static constexpr bool __IS_EXPRESSION__ = true;
78+
79+
constexpr explicit MulExpression(LhsType&& lhs, RhsType&& rhs)
80+
: lhs(std::forward<LhsType>(lhs))
81+
, rhs(std::forward<RhsType>(rhs))
82+
{}
83+
};
84+
85+
template <typename InnerType>
86+
constexpr NegExpression<InnerType> operator-(InnerType&& inner)
87+
requires(InnerType::__IS_EXPRESSION__)
88+
{
89+
return NegExpression<InnerType>(std::forward<InnerType>(inner));
90+
}
91+
92+
template <typename LhsType, typename RhsType>
93+
constexpr AddExpression<LhsType, RhsType> operator+(LhsType&& lhs, RhsType&& rhs)
94+
requires(LhsType::__IS_EXPRESSION__ && RhsType::__IS_EXPRESSION__)
95+
{
96+
return AddExpression<LhsType, RhsType>(std::forward<LhsType>(lhs), std::forward<RhsType>(rhs));
97+
}
98+
99+
template <typename LhsType, typename RhsType>
100+
constexpr SubExpression<LhsType, RhsType> operator-(LhsType&& lhs, RhsType&& rhs)
101+
requires(LhsType::__IS_EXPRESSION__ && RhsType::__IS_EXPRESSION__)
102+
{
103+
return SubExpression<LhsType, RhsType>(std::forward<LhsType>(lhs), std::forward<RhsType>(rhs));
104+
}
105+
106+
template <typename LhsType, typename RhsType>
107+
constexpr MulExpression<LhsType, RhsType> operator*(LhsType&& lhs, RhsType&& rhs)
108+
requires(LhsType::__IS_EXPRESSION__ && RhsType::__IS_EXPRESSION__)
109+
{
110+
return MulExpression<LhsType, RhsType>(std::forward<LhsType>(lhs), std::forward<RhsType>(rhs));
111+
}
112+
113+
} // namespace bb::avm2
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#pragma once
2+
3+
#include "barretenberg/vm2/common/expression.hpp"
4+
5+
namespace bb::avm2 {
6+
7+
/**
8+
* @brief Returns the degree of an expression.
9+
*
10+
* It can be used at copile time.
11+
*/
12+
class DegreeExpressionEvaluator {
13+
public:
14+
static constexpr size_t evaluate(const ConstantExpression&) { return 0; }
15+
static constexpr size_t evaluate(const ColumnExpression&) { return 1; }
16+
17+
template <typename InnerType> static constexpr size_t evaluate(const NegExpression<InnerType>& expression)
18+
{
19+
return evaluate(expression.inner);
20+
}
21+
22+
template <typename LhsType, typename RhsType>
23+
static constexpr size_t evaluate(const AddExpression<LhsType, RhsType>& expression)
24+
{
25+
return std::max(evaluate(expression.lhs), evaluate(expression.rhs));
26+
}
27+
28+
template <typename LhsType, typename RhsType>
29+
static constexpr size_t evaluate(const SubExpression<LhsType, RhsType>& expression)
30+
{
31+
return std::max(evaluate(expression.lhs), evaluate(expression.rhs));
32+
}
33+
34+
template <typename LhsType, typename RhsType>
35+
static constexpr size_t evaluate(const MulExpression<LhsType, RhsType>& expression)
36+
{
37+
return evaluate(expression.lhs) + evaluate(expression.rhs);
38+
}
39+
};
40+
41+
/**
42+
* @brief Evaluates an expression to a value.
43+
*/
44+
template <typename ValueType> class ValueExpressionEvaluator {
45+
public:
46+
using ColumnEvaluator = std::function<ValueType(const ColumnExpression&)>;
47+
ValueExpressionEvaluator(ColumnEvaluator column_evaluator)
48+
: column_evaluator_(std::move(column_evaluator))
49+
{}
50+
51+
ValueType evaluate(const ConstantExpression& expression) const { return expression.value; }
52+
ValueType evaluate(const ColumnExpression& expression) const { return column_evaluator_(expression); }
53+
54+
template <typename InnerType> ValueType evaluate(const NegExpression<InnerType>& expression) const
55+
{
56+
return -evaluate(expression.inner);
57+
}
58+
59+
template <typename LhsType, typename RhsType>
60+
ValueType evaluate(const AddExpression<LhsType, RhsType>& expression) const
61+
{
62+
return evaluate(expression.lhs) + evaluate(expression.rhs);
63+
}
64+
65+
template <typename LhsType, typename RhsType>
66+
ValueType evaluate(const SubExpression<LhsType, RhsType>& expression) const
67+
{
68+
return evaluate(expression.lhs) - evaluate(expression.rhs);
69+
}
70+
71+
template <typename LhsType, typename RhsType>
72+
ValueType evaluate(const MulExpression<LhsType, RhsType>& expression) const
73+
{
74+
return evaluate(expression.lhs) * evaluate(expression.rhs);
75+
}
76+
77+
private:
78+
ColumnEvaluator column_evaluator_;
79+
};
80+
} // namespace bb::avm2
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include "barretenberg/vm2/common/expression_evaluation.hpp"
2+
3+
namespace bb::avm2 {
4+
5+
static_assert(DegreeExpressionEvaluator::evaluate(ConstantExpression(33) +
6+
ColumnExpression(ColumnAndShifts::memory_clk)) == 1);
7+
static_assert(DegreeExpressionEvaluator::evaluate(ColumnExpression(ColumnAndShifts::context_stack_is_static) *
8+
ColumnExpression(ColumnAndShifts::memory_clk)) == 2);
9+
static_assert(DegreeExpressionEvaluator::evaluate(-ConstantExpression(33)) == 0);
10+
static_assert(DegreeExpressionEvaluator::evaluate(-ColumnExpression(ColumnAndShifts::memory_clk)) == 1);
11+
static_assert(DegreeExpressionEvaluator::evaluate(-(-ConstantExpression(33))) == 0);
12+
static_assert(DegreeExpressionEvaluator::evaluate(-(-ColumnExpression(ColumnAndShifts::memory_clk))) == 1);
13+
static_assert(DegreeExpressionEvaluator::evaluate(ConstantExpression(33) -
14+
ColumnExpression(ColumnAndShifts::memory_clk)) == 1);
15+
static_assert(DegreeExpressionEvaluator::evaluate(ColumnExpression(ColumnAndShifts::context_stack_is_static) -
16+
ColumnExpression(ColumnAndShifts::memory_clk)) == 1);
17+
static_assert(DegreeExpressionEvaluator::evaluate(ConstantExpression(33) *
18+
ColumnExpression(ColumnAndShifts::memory_clk)) == 1);
19+
static_assert(DegreeExpressionEvaluator::evaluate(ColumnExpression(ColumnAndShifts::context_stack_is_static) *
20+
ColumnExpression(ColumnAndShifts::memory_clk)) == 2);
21+
22+
} // namespace bb::avm2

barretenberg/cpp/src/barretenberg/vm2/constraining/relations/interactions_base.hpp

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
#pragma once
22

33
#include <cstddef>
4+
#include <type_traits>
5+
#include <utility>
46

57
#include "barretenberg/common/tuple.hpp"
68
#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp"
79
#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp"
10+
#include "barretenberg/vm2/common/expression.hpp"
11+
#include "barretenberg/vm2/common/expression_evaluation.hpp"
812
#include "barretenberg/vm2/generated/columns.hpp"
913

1014
namespace bb::avm2 {
@@ -20,34 +24,55 @@ template <typename Settings_> struct lookup_settings : public Settings_ {
2024
static constexpr size_t READ_TERM_DEGREE = 0;
2125
static constexpr size_t WRITE_TERM_DEGREE = 0;
2226

27+
// TODO(fcarreiro): support any degree.
28+
// static constexpr size_t MAX_DEGREE = std::max(
29+
// { DegreeExpressionEvaluator::evaluate(Settings_::SRC_SELECTOR_EXPR),
30+
// DegreeExpressionEvaluator::evaluate(Settings_::DST_SELECTOR_EXPR),
31+
// []<size_t... ISource, size_t... IDest>(std::index_sequence<ISource...>, std::index_sequence<IDest...>) {
32+
// return std::max(DegreeExpressionEvaluator::evaluate(std::get<ISource>(Settings_::SRC_EXPRS))...,
33+
// DegreeExpressionEvaluator::evaluate(std::get<IDest>(Settings_::DST_EXPRS))...);
34+
// }(std::make_index_sequence<std::tuple_size_v<decltype(Settings_::SRC_EXPRS)>>{},
35+
// std::make_index_sequence<std::tuple_size_v<decltype(Settings_::DST_EXPRS)>>{}) });
36+
// // The GenericLookupRelation only safely supports degree <= 1 for each expression.
37+
// static_assert(MAX_DEGREE <= 1, "MAX_DEGREE of lookup must be less than 1");
38+
2339
template <typename AllEntities> static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in)
2440
{
25-
return (in.get(static_cast<ColumnAndShifts>(Settings_::SRC_SELECTOR)) == 1 ||
26-
in.get(static_cast<ColumnAndShifts>(Settings_::DST_SELECTOR)) == 1);
41+
using RetType =
42+
decltype(std::declval<const std::remove_reference_t<AllEntities>&>().get(std::declval<ColumnAndShifts>()));
43+
auto ev =
44+
ValueExpressionEvaluator<RetType>([&in](const ColumnExpression& expr) { return in.get(expr.column); });
45+
return (ev.evaluate(Settings_::SRC_SELECTOR_EXPR) == 1 || ev.evaluate(Settings_::DST_SELECTOR_EXPR) == 1);
2746
}
2847

2948
template <typename Accumulator, typename AllEntities>
3049
static inline auto compute_inverse_exists(const AllEntities& in)
3150
{
3251
using View = typename Accumulator::View;
33-
const auto is_operation = View(in.get(static_cast<ColumnAndShifts>(Settings_::SRC_SELECTOR)));
34-
const auto is_table_entry = View(in.get(static_cast<ColumnAndShifts>(Settings_::DST_SELECTOR)));
52+
auto ev =
53+
ValueExpressionEvaluator<View>([&in](const ColumnExpression& expr) { return View(in.get(expr.column)); });
54+
const auto is_operation = ev.evaluate(Settings_::SRC_SELECTOR_EXPR);
55+
const auto is_table_entry = ev.evaluate(Settings_::DST_SELECTOR_EXPR);
3556
return (is_operation + is_table_entry - is_operation * is_table_entry);
3657
}
3758

3859
template <typename AllEntities> static inline auto get_entities(AllEntities&& in)
3960
{
4061
return []<size_t... ISource, size_t... IDest>(
4162
AllEntities&& in, std::index_sequence<ISource...>, std::index_sequence<IDest...>) {
63+
using RetType = decltype(std::declval<const std::remove_reference_t<AllEntities>&>().get(
64+
std::declval<ColumnAndShifts>()));
65+
auto ev =
66+
ValueExpressionEvaluator<RetType>([&in](const ColumnExpression& expr) { return in.get(expr.column); });
4267
return flat_tuple::forward_as_tuple(in.get(static_cast<ColumnAndShifts>(Settings_::INVERSES)),
4368
in.get(static_cast<ColumnAndShifts>(Settings_::COUNTS)),
44-
in.get(static_cast<ColumnAndShifts>(Settings_::SRC_SELECTOR)),
45-
in.get(static_cast<ColumnAndShifts>(Settings_::DST_SELECTOR)),
46-
in.get(Settings_::SRC_COLUMNS[ISource])...,
47-
in.get(Settings_::DST_COLUMNS[IDest])...);
69+
ev.evaluate(Settings_::SRC_SELECTOR_EXPR),
70+
ev.evaluate(Settings_::DST_SELECTOR_EXPR),
71+
ev.evaluate(std::get<ISource>(Settings_::SRC_EXPRS))...,
72+
ev.evaluate(std::get<IDest>(Settings_::DST_EXPRS))...);
4873
}(std::forward<AllEntities>(in),
49-
std::make_index_sequence<Settings_::SRC_COLUMNS.size()>{},
50-
std::make_index_sequence<Settings_::DST_COLUMNS.size()>{});
74+
std::make_index_sequence<std::tuple_size_v<decltype(Settings_::SRC_EXPRS)>>{},
75+
std::make_index_sequence<std::tuple_size_v<decltype(Settings_::DST_EXPRS)>>{});
5176
}
5277

5378
template <typename AllEntities> static inline auto get_const_entities(const AllEntities& in)

0 commit comments

Comments
 (0)