22#include <gtest/gtest.h>
31static constexpr size_t NUM_SUBRELATIONS = 3;
37 const auto& beta = params.
beta;
38 const auto& beta_sqr = params.
beta_sqr;
40 const auto& gamma = params.
gamma;
41 const auto derived_1 = in[EntityId::w_l] + gamma + in[EntityId::q_r] * in[EntityId::w_l_shift];
42 const auto derived_2 = in[EntityId::w_r] + in[EntityId::q_m] * in[EntityId::w_r_shift];
43 const auto derived_3 = in[EntityId::w_o] + in[EntityId::q_c] * in[EntityId::w_o_shift];
44 return derived_1 + derived_2 * beta + derived_3 * beta_sqr + in[EntityId::q_o] * beta_cube;
50 const auto& beta = params.
beta;
51 const auto& beta_sqr = params.
beta_sqr;
53 const auto& gamma = params.
gamma;
54 return in[EntityId::table_1] + gamma + in[EntityId::table_2] * beta + in[EntityId::table_3] * beta_sqr +
55 in[EntityId::table_4] * beta_cube;
59static FF compute_inverse_exists(
const Inputs& in)
61 const FF q_lookup = in[EntityId::q_lookup];
62 const FF read_tag = in[EntityId::lookup_read_tags];
63 return q_lookup + read_tag - q_lookup * read_tag;
69 const FF& scaling_factor)
71 const FF L = compute_L(in, params);
72 const FF T = compute_T(in, params);
73 const FF I = in[EntityId::lookup_inverses];
74 const FF q_lookup = in[EntityId::q_lookup];
75 const FF read_counts = in[EntityId::lookup_read_counts];
76 const FF read_tag = in[EntityId::lookup_read_tags];
77 const FF inverse_exists = compute_inverse_exists(in);
79 (L * T * I - inverse_exists) * scaling_factor,
80 (q_lookup * T - read_counts * L) * I,
81 (read_tag * read_tag - read_tag) * scaling_factor
88 const FF& scaling_factor =
FF(1))
104 FF table_idx =
FF(1))
107 in[EntityId::q_lookup] =
FF(1);
109 in[EntityId::q_r] =
FF(0);
110 in[EntityId::q_m] =
FF(0);
111 in[EntityId::q_c] =
FF(0);
112 in[EntityId::w_l] = entry_1;
113 in[EntityId::w_r] = entry_2;
114 in[EntityId::w_o] = entry_3;
115 in[EntityId::q_o] = table_idx;
117 in[EntityId::table_1] = entry_1;
118 in[EntityId::table_2] = entry_2;
119 in[EntityId::table_3] = entry_3;
120 in[EntityId::table_4] = table_idx;
121 in[EntityId::lookup_read_counts] =
FF(1);
122 in[EntityId::lookup_read_tags] =
FF(1);
123 const FF L = compute_L(in, params);
124 const FF T = compute_T(in, params);
125 in[EntityId::lookup_inverses] = (L * T).invert();
130static Inputs make_random_row()
133 for (
auto id : { EntityId::w_l,
148 EntityId::lookup_inverses,
149 EntityId::lookup_read_counts,
150 EntityId::lookup_read_tags }) {
163 for (
auto in : { make_random_row(), make_valid_lookup_row(params) }) {
166 EXPECT_EQ(actual, compute_expected_values(in, params, scaling_factor));
176 const auto acc = eval_row(in, params);
177 for (
size_t i = 0; i < NUM_SUBRELATIONS; ++i) {
178 EXPECT_EQ(acc[i],
FF(0)) <<
"Subrelation " << i <<
" should be zero on inactive row";
186 auto in = make_valid_lookup_row(params,
FF(7),
FF(11),
FF(13));
187 const auto acc = eval_row(in, params);
188 EXPECT_EQ(acc[0],
FF(0));
189 EXPECT_EQ(acc[1],
FF(0));
190 EXPECT_EQ(acc[2],
FF(0));
200 in[EntityId::table_1] =
FF(7);
201 in[EntityId::table_2] =
FF(11);
202 in[EntityId::table_3] =
FF(13);
203 in[EntityId::table_4] =
FF(1);
204 in[EntityId::lookup_read_counts] =
FF(3);
205 in[EntityId::lookup_read_tags] =
FF(1);
206 const FF L = compute_L(in, params);
207 const FF T = compute_T(in, params);
208 in[EntityId::lookup_inverses] = (L * T).invert();
209 const auto acc = eval_row(in, params);
210 EXPECT_EQ(acc[0],
FF(0));
211 EXPECT_EQ(acc[1], (
FF(0) * T -
FF(3) * L) * in[EntityId::lookup_inverses]);
212 EXPECT_NE(acc[1],
FF(0));
213 EXPECT_EQ(acc[2],
FF(0));
222 auto row_a = make_valid_lookup_row(params,
FF(7),
FF(11),
FF(13),
FF(1));
223 row_a[EntityId::table_1] =
FF(0);
224 row_a[EntityId::table_2] =
FF(0);
225 row_a[EntityId::table_3] =
FF(0);
226 row_a[EntityId::table_4] =
FF(0);
227 row_a[EntityId::lookup_read_counts] =
FF(0);
228 row_a[EntityId::lookup_read_tags] =
FF(0);
230 const FF L = compute_L(row_a, params);
231 const FF T = compute_T(row_a, params);
232 row_a[EntityId::lookup_inverses] = (L * T).invert();
237 row_b[EntityId::table_1] =
FF(7);
238 row_b[EntityId::table_2] =
FF(11);
239 row_b[EntityId::table_3] =
FF(13);
240 row_b[EntityId::table_4] =
FF(1);
241 row_b[EntityId::lookup_read_counts] =
FF(1);
242 row_b[EntityId::lookup_read_tags] =
FF(1);
243 const FF L_b = compute_L(row_b, params);
244 const FF T_b = compute_T(row_b, params);
245 row_b[EntityId::lookup_inverses] = (L_b * T_b).invert();
250 EXPECT_EQ(acc[0],
FF(0));
251 EXPECT_EQ(acc[1],
FF(0));
252 EXPECT_EQ(acc[2],
FF(0));
259 auto in = make_valid_lookup_row(params);
260 in[EntityId::lookup_inverses] =
FF(42);
262 const FF L = compute_L(in, params);
263 const FF T = compute_T(in, params);
264 const FF inverse_exists = compute_inverse_exists(in);
265 const auto acc = eval_row(in, params);
266 EXPECT_EQ(acc[0], (L * T *
FF(42) - inverse_exists) *
FF(1));
267 EXPECT_NE(acc[0],
FF(0));
278 in[EntityId::w_l] =
FF(7);
279 in[EntityId::w_r] =
FF(11);
280 in[EntityId::w_o] =
FF(13);
281 in[EntityId::table_1] =
FF(17);
282 in[EntityId::table_2] =
FF(19);
283 in[EntityId::table_3] =
FF(23);
284 in[EntityId::table_4] =
FF(29);
288 in[EntityId::lookup_inverses] =
FF(0);
290 const auto acc = eval_row(in, params);
291 for (
size_t i = 0; i < NUM_SUBRELATIONS; ++i) {
292 EXPECT_EQ(acc[i],
FF(0)) <<
"Subrelation " << i <<
" should vanish on inactive row when I = 0";
297 in[EntityId::lookup_inverses] =
FF(123);
299 const FF L = compute_L(in, params);
300 const FF T = compute_T(in, params);
301 const auto acc = eval_row(in, params);
302 EXPECT_EQ(acc[0], L * T *
FF(123));
303 EXPECT_NE(acc[0],
FF(0));
314 auto row_a = make_valid_lookup_row(params,
FF(7),
FF(11),
FF(13),
FF(1));
315 row_a[EntityId::table_1] =
FF(0);
316 row_a[EntityId::table_2] =
FF(0);
317 row_a[EntityId::table_3] =
FF(0);
318 row_a[EntityId::table_4] =
FF(0);
319 row_a[EntityId::lookup_read_counts] =
FF(0);
320 row_a[EntityId::lookup_read_tags] =
FF(0);
322 const FF L = compute_L(row_a, params);
323 const FF T = compute_T(row_a, params);
324 row_a[EntityId::lookup_inverses] = (L * T).invert();
329 row_b[EntityId::table_1] =
FF(7);
330 row_b[EntityId::table_2] =
FF(11);
331 row_b[EntityId::table_3] =
FF(13);
332 row_b[EntityId::table_4] =
FF(1);
333 row_b[EntityId::lookup_read_counts] =
FF(2);
334 row_b[EntityId::lookup_read_tags] =
FF(1);
335 const FF L_b = compute_L(row_b, params);
336 const FF T_b = compute_T(row_b, params);
337 row_b[EntityId::lookup_inverses] = (L_b * T_b).invert();
342 EXPECT_EQ(acc[0],
FF(0));
343 EXPECT_NE(acc[1],
FF(0));
344 EXPECT_EQ(acc[2],
FF(0));
352 in[EntityId::lookup_read_tags] =
FF(5);
353 const auto acc = eval_row(in, params);
354 EXPECT_EQ(acc[2],
FF(5) *
FF(5) -
FF(5));
355 EXPECT_NE(acc[2],
FF(0));
364 in[EntityId::q_lookup] =
FF(1);
367 in[EntityId::q_lookup] =
FF(0);
368 in[EntityId::lookup_read_counts] =
FF(3);
381 auto lookup_row = make_valid_lookup_row(params,
FF(0),
FF(0),
FF(0),
FF(1));
382 lookup_row[EntityId::lookup_read_counts] =
FF(0);
383 lookup_row[EntityId::lookup_read_tags] =
FF(0);
384 const FF L = compute_L(lookup_row, params);
385 const FF T = compute_T(lookup_row, params);
386 lookup_row[EntityId::lookup_inverses] = (L * T).invert();
388 const auto acc = eval_row(lookup_row, params);
389 EXPECT_EQ(acc[0], 0);
391 EXPECT_EQ(acc[2], 0);
Log-derivative lookup argument relation for establishing lookup reads from tables with 3 or fewer col...
static void accumulate(ContainerOverSubrelations &accumulator, const AllEntities &in, const Parameters ¶ms, const FF &scaling_factor)
Accumulate the subrelation contributions for reads from a lookup table.
static bool skip(const AllEntities &in)
UltraFlavor_Generated::EntityId EntityId
std::array< FF, NUM_SUBRELATIONS > SubrelationAccumulator
Entry point for Barretenberg command-line interface.
TEST_F(IPATest, ChallengesAreZero)
field< Bn254FrParams > fr
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Container for parameters used by the grand product (permutation, lookup) Honk relations.
static RelationParameters get_random()
static field random_element(numeric::RNG *engine=nullptr) noexcept