Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
poseidon2_perm_impl.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <array>
6
9
10namespace bb::avm2 {
11
12template <typename FF_>
13template <typename ContainerOverSubrelations, typename AllEntities>
14void optimized_poseidon2_permImpl<FF_>::accumulate(ContainerOverSubrelations& evals,
15 const AllEntities& in,
16 [[maybe_unused]] const RelationParameters<FF_>&,
17 [[maybe_unused]] const FF_& scaling_factor)
18{
19 using Poseidon2Params = crypto::Poseidon2Bn254ScalarFieldParams;
20 using C = ColumnAndShifts;
21
22 // Note this vector is arranged in *subrelation* order NOT in state order
23 // Refer to generated/poseidon2_perm_impl.hpp for the order of subrelations in each round
24 std::array<std::array<C, 4>, 64> round_cols = { {
25 //=========================================
26 // Initial Full Round Columns
27 //=========================================
28 { C::poseidon2_perm_T_0_4, C::poseidon2_perm_T_0_5, C::poseidon2_perm_T_0_6, C::poseidon2_perm_T_0_7 },
29 { C::poseidon2_perm_T_1_4, C::poseidon2_perm_T_1_5, C::poseidon2_perm_T_1_6, C::poseidon2_perm_T_1_7 },
30 { C::poseidon2_perm_T_2_4, C::poseidon2_perm_T_2_5, C::poseidon2_perm_T_2_6, C::poseidon2_perm_T_2_7 },
31 { C::poseidon2_perm_T_3_4, C::poseidon2_perm_T_3_5, C::poseidon2_perm_T_3_6, C::poseidon2_perm_T_3_7 },
32 //=========================================
33 // Partial Round Columns
34 //=========================================
35 { C::poseidon2_perm_B_4_0, C::poseidon2_perm_B_4_1, C::poseidon2_perm_B_4_2, C::poseidon2_perm_B_4_3 },
36 { C::poseidon2_perm_B_5_0, C::poseidon2_perm_B_5_1, C::poseidon2_perm_B_5_2, C::poseidon2_perm_B_5_3 },
37 { C::poseidon2_perm_B_6_0, C::poseidon2_perm_B_6_1, C::poseidon2_perm_B_6_2, C::poseidon2_perm_B_6_3 },
38 { C::poseidon2_perm_B_7_0, C::poseidon2_perm_B_7_1, C::poseidon2_perm_B_7_2, C::poseidon2_perm_B_7_3 },
39 { C::poseidon2_perm_B_8_0, C::poseidon2_perm_B_8_1, C::poseidon2_perm_B_8_2, C::poseidon2_perm_B_8_3 },
40 { C::poseidon2_perm_B_9_0, C::poseidon2_perm_B_9_1, C::poseidon2_perm_B_9_2, C::poseidon2_perm_B_9_3 },
41 { C::poseidon2_perm_B_10_0, C::poseidon2_perm_B_10_1, C::poseidon2_perm_B_10_2, C::poseidon2_perm_B_10_3 },
42 { C::poseidon2_perm_B_11_0, C::poseidon2_perm_B_11_1, C::poseidon2_perm_B_11_2, C::poseidon2_perm_B_11_3 },
43 { C::poseidon2_perm_B_12_0, C::poseidon2_perm_B_12_1, C::poseidon2_perm_B_12_2, C::poseidon2_perm_B_12_3 },
44 { C::poseidon2_perm_B_13_0, C::poseidon2_perm_B_13_1, C::poseidon2_perm_B_13_2, C::poseidon2_perm_B_13_3 },
45 { C::poseidon2_perm_B_14_0, C::poseidon2_perm_B_14_1, C::poseidon2_perm_B_14_2, C::poseidon2_perm_B_14_3 },
46 { C::poseidon2_perm_B_15_0, C::poseidon2_perm_B_15_1, C::poseidon2_perm_B_15_2, C::poseidon2_perm_B_15_3 },
47 { C::poseidon2_perm_B_16_0, C::poseidon2_perm_B_16_1, C::poseidon2_perm_B_16_2, C::poseidon2_perm_B_16_3 },
48 { C::poseidon2_perm_B_17_0, C::poseidon2_perm_B_17_1, C::poseidon2_perm_B_17_2, C::poseidon2_perm_B_17_3 },
49 { C::poseidon2_perm_B_18_0, C::poseidon2_perm_B_18_1, C::poseidon2_perm_B_18_2, C::poseidon2_perm_B_18_3 },
50 { C::poseidon2_perm_B_19_0, C::poseidon2_perm_B_19_1, C::poseidon2_perm_B_19_2, C::poseidon2_perm_B_19_3 },
51 { C::poseidon2_perm_B_20_0, C::poseidon2_perm_B_20_1, C::poseidon2_perm_B_20_2, C::poseidon2_perm_B_20_3 },
52 { C::poseidon2_perm_B_21_0, C::poseidon2_perm_B_21_1, C::poseidon2_perm_B_21_2, C::poseidon2_perm_B_21_3 },
53 { C::poseidon2_perm_B_22_0, C::poseidon2_perm_B_22_1, C::poseidon2_perm_B_22_2, C::poseidon2_perm_B_22_3 },
54 { C::poseidon2_perm_B_23_0, C::poseidon2_perm_B_23_1, C::poseidon2_perm_B_23_2, C::poseidon2_perm_B_23_3 },
55 { C::poseidon2_perm_B_24_0, C::poseidon2_perm_B_24_1, C::poseidon2_perm_B_24_2, C::poseidon2_perm_B_24_3 },
56 { C::poseidon2_perm_B_25_0, C::poseidon2_perm_B_25_1, C::poseidon2_perm_B_25_2, C::poseidon2_perm_B_25_3 },
57 { C::poseidon2_perm_B_26_0, C::poseidon2_perm_B_26_1, C::poseidon2_perm_B_26_2, C::poseidon2_perm_B_26_3 },
58 { C::poseidon2_perm_B_27_0, C::poseidon2_perm_B_27_1, C::poseidon2_perm_B_27_2, C::poseidon2_perm_B_27_3 },
59 { C::poseidon2_perm_B_28_0, C::poseidon2_perm_B_28_1, C::poseidon2_perm_B_28_2, C::poseidon2_perm_B_28_3 },
60 { C::poseidon2_perm_B_29_0, C::poseidon2_perm_B_29_1, C::poseidon2_perm_B_29_2, C::poseidon2_perm_B_29_3 },
61 { C::poseidon2_perm_B_30_0, C::poseidon2_perm_B_30_1, C::poseidon2_perm_B_30_2, C::poseidon2_perm_B_30_3 },
62 { C::poseidon2_perm_B_31_0, C::poseidon2_perm_B_31_1, C::poseidon2_perm_B_31_2, C::poseidon2_perm_B_31_3 },
63 { C::poseidon2_perm_B_32_0, C::poseidon2_perm_B_32_1, C::poseidon2_perm_B_32_2, C::poseidon2_perm_B_32_3 },
64 { C::poseidon2_perm_B_33_0, C::poseidon2_perm_B_33_1, C::poseidon2_perm_B_33_2, C::poseidon2_perm_B_33_3 },
65 { C::poseidon2_perm_B_34_0, C::poseidon2_perm_B_34_1, C::poseidon2_perm_B_34_2, C::poseidon2_perm_B_34_3 },
66 { C::poseidon2_perm_B_35_0, C::poseidon2_perm_B_35_1, C::poseidon2_perm_B_35_2, C::poseidon2_perm_B_35_3 },
67 { C::poseidon2_perm_B_36_0, C::poseidon2_perm_B_36_1, C::poseidon2_perm_B_36_2, C::poseidon2_perm_B_36_3 },
68 { C::poseidon2_perm_B_37_0, C::poseidon2_perm_B_37_1, C::poseidon2_perm_B_37_2, C::poseidon2_perm_B_37_3 },
69 { C::poseidon2_perm_B_38_0, C::poseidon2_perm_B_38_1, C::poseidon2_perm_B_38_2, C::poseidon2_perm_B_38_3 },
70 { C::poseidon2_perm_B_39_0, C::poseidon2_perm_B_39_1, C::poseidon2_perm_B_39_2, C::poseidon2_perm_B_39_3 },
71 { C::poseidon2_perm_B_40_0, C::poseidon2_perm_B_40_1, C::poseidon2_perm_B_40_2, C::poseidon2_perm_B_40_3 },
72 { C::poseidon2_perm_B_41_0, C::poseidon2_perm_B_41_1, C::poseidon2_perm_B_41_2, C::poseidon2_perm_B_41_3 },
73 { C::poseidon2_perm_B_42_0, C::poseidon2_perm_B_42_1, C::poseidon2_perm_B_42_2, C::poseidon2_perm_B_42_3 },
74 { C::poseidon2_perm_B_43_0, C::poseidon2_perm_B_43_1, C::poseidon2_perm_B_43_2, C::poseidon2_perm_B_43_3 },
75 { C::poseidon2_perm_B_44_0, C::poseidon2_perm_B_44_1, C::poseidon2_perm_B_44_2, C::poseidon2_perm_B_44_3 },
76 { C::poseidon2_perm_B_45_0, C::poseidon2_perm_B_45_1, C::poseidon2_perm_B_45_2, C::poseidon2_perm_B_45_3 },
77 { C::poseidon2_perm_B_46_0, C::poseidon2_perm_B_46_1, C::poseidon2_perm_B_46_2, C::poseidon2_perm_B_46_3 },
78 { C::poseidon2_perm_B_47_0, C::poseidon2_perm_B_47_1, C::poseidon2_perm_B_47_2, C::poseidon2_perm_B_47_3 },
79 { C::poseidon2_perm_B_48_0, C::poseidon2_perm_B_48_1, C::poseidon2_perm_B_48_2, C::poseidon2_perm_B_48_3 },
80 { C::poseidon2_perm_B_49_0, C::poseidon2_perm_B_49_1, C::poseidon2_perm_B_49_2, C::poseidon2_perm_B_49_3 },
81 { C::poseidon2_perm_B_50_0, C::poseidon2_perm_B_50_1, C::poseidon2_perm_B_50_2, C::poseidon2_perm_B_50_3 },
82 { C::poseidon2_perm_B_51_0, C::poseidon2_perm_B_51_1, C::poseidon2_perm_B_51_2, C::poseidon2_perm_B_51_3 },
83 { C::poseidon2_perm_B_52_0, C::poseidon2_perm_B_52_1, C::poseidon2_perm_B_52_2, C::poseidon2_perm_B_52_3 },
84 { C::poseidon2_perm_B_53_0, C::poseidon2_perm_B_53_1, C::poseidon2_perm_B_53_2, C::poseidon2_perm_B_53_3 },
85 { C::poseidon2_perm_B_54_0, C::poseidon2_perm_B_54_1, C::poseidon2_perm_B_54_2, C::poseidon2_perm_B_54_3 },
86 { C::poseidon2_perm_B_55_0, C::poseidon2_perm_B_55_1, C::poseidon2_perm_B_55_2, C::poseidon2_perm_B_55_3 },
87 { C::poseidon2_perm_B_56_0, C::poseidon2_perm_B_56_1, C::poseidon2_perm_B_56_2, C::poseidon2_perm_B_56_3 },
88 { C::poseidon2_perm_B_57_0, C::poseidon2_perm_B_57_1, C::poseidon2_perm_B_57_2, C::poseidon2_perm_B_57_3 },
89 { C::poseidon2_perm_B_58_0, C::poseidon2_perm_B_58_1, C::poseidon2_perm_B_58_2, C::poseidon2_perm_B_58_3 },
90 { C::poseidon2_perm_B_59_0, C::poseidon2_perm_B_59_1, C::poseidon2_perm_B_59_2, C::poseidon2_perm_B_59_3 },
91 //=========================================
92 // Final Full Round Columns
93 //=========================================
94 { C::poseidon2_perm_T_60_4, C::poseidon2_perm_T_60_5, C::poseidon2_perm_T_60_6, C::poseidon2_perm_T_60_7 },
95 { C::poseidon2_perm_T_61_4, C::poseidon2_perm_T_61_5, C::poseidon2_perm_T_61_6, C::poseidon2_perm_T_61_7 },
96 { C::poseidon2_perm_T_62_4, C::poseidon2_perm_T_62_5, C::poseidon2_perm_T_62_6, C::poseidon2_perm_T_62_7 },
97 { C::poseidon2_perm_T_63_4, C::poseidon2_perm_T_63_5, C::poseidon2_perm_T_63_6, C::poseidon2_perm_T_63_7 },
98 } };
99
100 //=========================================
101 // HELPER FUNCTIONS
102 //=========================================
103 const auto full_round_add_constant = []<typename T, typename U>(std::array<T, 4>& state,
104 const std::array<U, 4>& rc) {
105 state[0] += rc[0];
106 state[1] += rc[1];
107 state[2] += rc[2];
108 state[3] += rc[3];
109 };
110
111 const auto full_round_s_box = []<typename T>(std::array<T, 4>& state) {
112 // For t = 4, the s-box is A^5, B^5, C^5, D^5
113 state[0] = state[0] * state[0] * state[0] * state[0] * state[0]; // A^5
114 state[1] = state[1] * state[1] * state[1] * state[1] * state[1]; // B^5
115 state[2] = state[2] * state[2] * state[2] * state[2] * state[2]; // C^5
116 state[3] = state[3] * state[3] * state[3] * state[3] * state[3]; // D^5
117 };
118
119 const auto external_matrix_mul = []<typename T>(std::array<T, 4>& state) {
120 // Taken from poseidon2 paper - Appendix B
121 auto t0 = state[0] + state[1];
122 auto t1 = state[2] + state[3];
123 auto t2 = FF(2) * state[1] + t1;
124 auto t3 = FF(2) * state[3] + t0;
125 auto t4 = FF(4) * t1 + t3;
126 auto t5 = FF(4) * t0 + t2;
127 auto t6 = t3 + t5;
128 auto t7 = t2 + t4;
129 state[0] = t6;
130 state[1] = t5;
131 state[2] = t7;
132 state[3] = t4;
133 };
134
135 // In partial round only the first state is updated
136 const auto partial_round_add_constant = []<typename T, typename U>(std::array<T, 4>& state, const U& rc) {
137 state[0] += rc;
138 };
139
140 // In partial round only the first state is updated
141 const auto partial_round_s_box = []<typename T>(std::array<T, 4>& state) {
142 state[0] = state[0] * state[0] * state[0] * state[0] * state[0]; // A^5
143 };
144
145 // The partial round uses the internal matrix diagonal values
146 const auto internal_matrix_mul = []<typename T, typename U>(std::array<T, 4>& state,
147 const std::array<U, 4>& internal_matrix_diagonal) {
148 auto sum = state[0] + state[1] + state[2] + state[3];
149 for (size_t i = 0; i < 4; ++i) {
150 state[i] = state[i] * internal_matrix_diagonal[i] + sum;
151 }
152 };
153
154 //=========================================
155 // Start Accumulation Relations
156 //=========================================
157 {
158 using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>;
159 auto tmp = in.get(C::poseidon2_perm_sel) * (FF(1) - in.get(C::poseidon2_perm_sel));
160 tmp *= scaling_factor;
161 std::get<0>(evals) += typename Accumulator::View(tmp);
162 }
163
164 // Initial state is the input
165 auto state = std::array{
166 in.get(C::poseidon2_perm_a_0),
167 in.get(C::poseidon2_perm_a_1),
168 in.get(C::poseidon2_perm_a_2),
169 in.get(C::poseidon2_perm_a_3),
170 };
171
172 //=========================================
173 // Start Permutation Algorithm
174 //=========================================
175 // The poseidon2 permutation algorithm consists of:
176 // 1) Initial External Matrix Multiplication
177 // 2) 4x Initial Full Rounds
178 // 3) 56x Partial Rounds
179 // 4) 4x Final Full Rounds
180
181 external_matrix_mul(state);
182 // Set the columns after the external matrix multiplication
183 {
184 using Accumulator = typename std::tuple_element_t<1, ContainerOverSubrelations>;
185 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(C::poseidon2_perm_EXT_LAYER_4) - state[3]);
186 tmp *= scaling_factor;
187 std::get<1>(evals) += typename Accumulator::View(tmp);
188 }
189 {
190 using Accumulator = typename std::tuple_element_t<2, ContainerOverSubrelations>;
191 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(C::poseidon2_perm_EXT_LAYER_5) - state[1]);
192 tmp *= scaling_factor;
193 std::get<2>(evals) += typename Accumulator::View(tmp);
194 }
195 {
196 using Accumulator = typename std::tuple_element_t<3, ContainerOverSubrelations>;
197 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(C::poseidon2_perm_EXT_LAYER_6) - state[0]);
198 tmp *= scaling_factor;
199 std::get<3>(evals) += typename Accumulator::View(tmp);
200 }
201 {
202 using Accumulator = typename std::tuple_element_t<4, ContainerOverSubrelations>;
203 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(C::poseidon2_perm_EXT_LAYER_7) - state[2]);
204 tmp *= scaling_factor;
205 std::get<4>(evals) += typename Accumulator::View(tmp);
206 }
207
208 // The permutation rounds start at subrelation index 5
209 constexpr size_t START_RELATION_OF_PERM = 5;
210 // We need to populate each state round with by retrieving the witness rather than mutating the state
211 // in place. Otherwise we do not end up with the correct subrelation length.
212 state = std::array{
213 in.get(C::poseidon2_perm_EXT_LAYER_6),
214 in.get(C::poseidon2_perm_EXT_LAYER_5),
215 in.get(C::poseidon2_perm_EXT_LAYER_7),
216 in.get(C::poseidon2_perm_EXT_LAYER_4),
217 };
218
219 // Start of the 4 Initial Full Rounds
220 constexpr_for<0, 4, 1>([&]<size_t i>() {
221 constexpr size_t relation_offset = START_RELATION_OF_PERM + (i * 4);
222 full_round_add_constant(state, Poseidon2Params::round_constants[i]);
223 full_round_s_box(state);
224 external_matrix_mul(state);
225 // Set state 0
226 {
228 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][0]) - state[3]);
229 tmp *= scaling_factor;
230 std::get<relation_offset>(evals) += typename Accumulator::View(tmp);
231 }
232 // Set state 1
233 {
235 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][1]) - state[1]);
236 tmp *= scaling_factor;
237 std::get<relation_offset + 1>(evals) += typename Accumulator::View(tmp);
238 }
239 // Set state 3
240 {
242 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][2]) - state[0]);
243 tmp *= scaling_factor;
244 std::get<relation_offset + 2>(evals) += typename Accumulator::View(tmp);
245 }
246 // Set state 4
247 {
249 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][3]) - state[2]);
250 tmp *= scaling_factor;
251 std::get<relation_offset + 3>(evals) += typename Accumulator::View(tmp);
252 }
253
254 // Set the state to be used in next round, this step helps to ensure subrelation length is correct
255 state = std::array{
256 in.get(round_cols[i][2]),
257 in.get(round_cols[i][1]),
258 in.get(round_cols[i][3]),
259 in.get(round_cols[i][0]),
260 };
261 });
262
263 // 56 Partial Rounds, from round 4 to round 60. (Note: This starts at relation 21)
264 constexpr_for<4, 60, 1>([&]<size_t i>() {
265 constexpr size_t relation_offset = START_RELATION_OF_PERM + (i * 4);
266 partial_round_add_constant(state, Poseidon2Params::round_constants[i][0]);
267 partial_round_s_box(state);
268 internal_matrix_mul(state, Poseidon2Params::internal_matrix_diagonal);
269 // Set the state 0
270 {
272 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][0]) - state[0]);
273 tmp *= scaling_factor;
274 std::get<relation_offset>(evals) += typename Accumulator::View(tmp);
275 }
276 // Set the state 1
277 {
279 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][1]) - state[1]);
280 tmp *= scaling_factor;
281 std::get<relation_offset + 1>(evals) += typename Accumulator::View(tmp);
282 }
283 // Set the state 2
284 {
286 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][2]) - state[2]);
287 tmp *= scaling_factor;
288 std::get<relation_offset + 2>(evals) += typename Accumulator::View(tmp);
289 }
290 // Set the state 3
291 {
293 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][3]) - state[3]);
294 tmp *= scaling_factor;
295 std::get<relation_offset + 3>(evals) += typename Accumulator::View(tmp);
296 }
297
298 // Set the state to be used in next round, this step helps to ensure subrelation length is correct
299 state = std::array{
300 in.get(round_cols[i][0]),
301 in.get(round_cols[i][1]),
302 in.get(round_cols[i][2]),
303 in.get(round_cols[i][3]),
304 };
305 });
306
307 // 4 Full Rounds, from round 60 to round 64. (Note: This starts at relation 245)
308 constexpr_for<60, 64, 1>([&]<size_t i>() {
309 constexpr size_t relation_offset = START_RELATION_OF_PERM + (i * 4);
310 full_round_add_constant(state, Poseidon2Params::round_constants[i]);
311 full_round_s_box(state);
312 external_matrix_mul(state);
313 // Set the state 0
314 {
316 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][0]) - state[3]);
317 tmp *= scaling_factor;
318 std::get<relation_offset>(evals) += typename Accumulator::View(tmp);
319 }
320 // Set the state 1
321 {
323 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][1]) - state[1]);
324 tmp *= scaling_factor;
325 std::get<relation_offset + 1>(evals) += typename Accumulator::View(tmp);
326 }
327 // Set the state 2
328 {
330 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][2]) - state[0]);
331 tmp *= scaling_factor;
332 std::get<relation_offset + 2>(evals) += typename Accumulator::View(tmp);
333 }
334 // Set the state 3
335 {
337 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(round_cols[i][3]) - state[2]);
338 tmp *= scaling_factor;
339 std::get<relation_offset + 3>(evals) += typename Accumulator::View(tmp);
340 }
341
342 // Set the state to be used in next round, this step helps to ensure subrelation length is correct
343 state = std::array{
344 in.get(round_cols[i][2]),
345 in.get(round_cols[i][1]),
346 in.get(round_cols[i][3]),
347 in.get(round_cols[i][0]),
348 };
349 });
350
351 // Write to outputs
352 {
353 using Accumulator = typename std::tuple_element_t<261, ContainerOverSubrelations>;
354 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(C::poseidon2_perm_b_0) - in.get(C::poseidon2_perm_T_63_6));
355 tmp *= scaling_factor;
356 std::get<261>(evals) += typename Accumulator::View(tmp);
357 }
358 {
359 using Accumulator = typename std::tuple_element_t<262, ContainerOverSubrelations>;
360 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(C::poseidon2_perm_b_1) - in.get(C::poseidon2_perm_T_63_5));
361 tmp *= scaling_factor;
362 std::get<262>(evals) += typename Accumulator::View(tmp);
363 }
364 {
365 using Accumulator = typename std::tuple_element_t<263, ContainerOverSubrelations>;
366 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(C::poseidon2_perm_b_2) - in.get(C::poseidon2_perm_T_63_7));
367 tmp *= scaling_factor;
368 std::get<263>(evals) += typename Accumulator::View(tmp);
369 }
370 {
371 using Accumulator = typename std::tuple_element_t<264, ContainerOverSubrelations>;
372 auto tmp = in.get(C::poseidon2_perm_sel) * (in.get(C::poseidon2_perm_b_3) - in.get(C::poseidon2_perm_T_63_4));
373 tmp *= scaling_factor;
374 std::get<264>(evals) += typename Accumulator::View(tmp);
375 }
376}
377
378} // namespace bb::avm2
static void accumulate(ContainerOverSubrelations &evals, const AllEntities &in, const RelationParameters< FF > &, const FF &scaling_factor)
ColumnAndShifts
Definition columns.hpp:34
AvmFlavorSettings::FF FF
Definition field.hpp:10
Inner sum(Cont< Inner, Args... > const &in)
Definition container.hpp:70
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Container for parameters used by the grand product (permutation, lookup) Honk relations.