36 { C::poseidon2_perm_B_4_0, C::poseidon2_perm_B_4_1, C::poseidon2_perm_B_4_2, C::poseidon2_perm_B_4_3 },
37 { C::poseidon2_perm_B_5_0, C::poseidon2_perm_B_5_1, C::poseidon2_perm_B_5_2, C::poseidon2_perm_B_5_3 },
38 { C::poseidon2_perm_B_6_0, C::poseidon2_perm_B_6_1, C::poseidon2_perm_B_6_2, C::poseidon2_perm_B_6_3 },
39 { C::poseidon2_perm_B_7_0, C::poseidon2_perm_B_7_1, C::poseidon2_perm_B_7_2, C::poseidon2_perm_B_7_3 },
40 { C::poseidon2_perm_B_8_0, C::poseidon2_perm_B_8_1, C::poseidon2_perm_B_8_2, C::poseidon2_perm_B_8_3 },
41 { C::poseidon2_perm_B_9_0, C::poseidon2_perm_B_9_1, C::poseidon2_perm_B_9_2, C::poseidon2_perm_B_9_3 },
42 { C::poseidon2_perm_B_10_0, C::poseidon2_perm_B_10_1, C::poseidon2_perm_B_10_2, C::poseidon2_perm_B_10_3 },
43 { C::poseidon2_perm_B_11_0, C::poseidon2_perm_B_11_1, C::poseidon2_perm_B_11_2, C::poseidon2_perm_B_11_3 },
44 { C::poseidon2_perm_B_12_0, C::poseidon2_perm_B_12_1, C::poseidon2_perm_B_12_2, C::poseidon2_perm_B_12_3 },
45 { C::poseidon2_perm_B_13_0, C::poseidon2_perm_B_13_1, C::poseidon2_perm_B_13_2, C::poseidon2_perm_B_13_3 },
46 { C::poseidon2_perm_B_14_0, C::poseidon2_perm_B_14_1, C::poseidon2_perm_B_14_2, C::poseidon2_perm_B_14_3 },
47 { C::poseidon2_perm_B_15_0, C::poseidon2_perm_B_15_1, C::poseidon2_perm_B_15_2, C::poseidon2_perm_B_15_3 },
48 { C::poseidon2_perm_B_16_0, C::poseidon2_perm_B_16_1, C::poseidon2_perm_B_16_2, C::poseidon2_perm_B_16_3 },
49 { C::poseidon2_perm_B_17_0, C::poseidon2_perm_B_17_1, C::poseidon2_perm_B_17_2, C::poseidon2_perm_B_17_3 },
50 { C::poseidon2_perm_B_18_0, C::poseidon2_perm_B_18_1, C::poseidon2_perm_B_18_2, C::poseidon2_perm_B_18_3 },
51 { C::poseidon2_perm_B_19_0, C::poseidon2_perm_B_19_1, C::poseidon2_perm_B_19_2, C::poseidon2_perm_B_19_3 },
52 { C::poseidon2_perm_B_20_0, C::poseidon2_perm_B_20_1, C::poseidon2_perm_B_20_2, C::poseidon2_perm_B_20_3 },
53 { C::poseidon2_perm_B_21_0, C::poseidon2_perm_B_21_1, C::poseidon2_perm_B_21_2, C::poseidon2_perm_B_21_3 },
54 { C::poseidon2_perm_B_22_0, C::poseidon2_perm_B_22_1, C::poseidon2_perm_B_22_2, C::poseidon2_perm_B_22_3 },
55 { C::poseidon2_perm_B_23_0, C::poseidon2_perm_B_23_1, C::poseidon2_perm_B_23_2, C::poseidon2_perm_B_23_3 },
56 { C::poseidon2_perm_B_24_0, C::poseidon2_perm_B_24_1, C::poseidon2_perm_B_24_2, C::poseidon2_perm_B_24_3 },
57 { C::poseidon2_perm_B_25_0, C::poseidon2_perm_B_25_1, C::poseidon2_perm_B_25_2, C::poseidon2_perm_B_25_3 },
58 { C::poseidon2_perm_B_26_0, C::poseidon2_perm_B_26_1, C::poseidon2_perm_B_26_2, C::poseidon2_perm_B_26_3 },
59 { C::poseidon2_perm_B_27_0, C::poseidon2_perm_B_27_1, C::poseidon2_perm_B_27_2, C::poseidon2_perm_B_27_3 },
60 { C::poseidon2_perm_B_28_0, C::poseidon2_perm_B_28_1, C::poseidon2_perm_B_28_2, C::poseidon2_perm_B_28_3 },
61 { C::poseidon2_perm_B_29_0, C::poseidon2_perm_B_29_1, C::poseidon2_perm_B_29_2, C::poseidon2_perm_B_29_3 },
62 { C::poseidon2_perm_B_30_0, C::poseidon2_perm_B_30_1, C::poseidon2_perm_B_30_2, C::poseidon2_perm_B_30_3 },
63 { C::poseidon2_perm_B_31_0, C::poseidon2_perm_B_31_1, C::poseidon2_perm_B_31_2, C::poseidon2_perm_B_31_3 },
64 { C::poseidon2_perm_B_32_0, C::poseidon2_perm_B_32_1, C::poseidon2_perm_B_32_2, C::poseidon2_perm_B_32_3 },
65 { C::poseidon2_perm_B_33_0, C::poseidon2_perm_B_33_1, C::poseidon2_perm_B_33_2, C::poseidon2_perm_B_33_3 },
66 { C::poseidon2_perm_B_34_0, C::poseidon2_perm_B_34_1, C::poseidon2_perm_B_34_2, C::poseidon2_perm_B_34_3 },
67 { C::poseidon2_perm_B_35_0, C::poseidon2_perm_B_35_1, C::poseidon2_perm_B_35_2, C::poseidon2_perm_B_35_3 },
68 { C::poseidon2_perm_B_36_0, C::poseidon2_perm_B_36_1, C::poseidon2_perm_B_36_2, C::poseidon2_perm_B_36_3 },
69 { C::poseidon2_perm_B_37_0, C::poseidon2_perm_B_37_1, C::poseidon2_perm_B_37_2, C::poseidon2_perm_B_37_3 },
70 { C::poseidon2_perm_B_38_0, C::poseidon2_perm_B_38_1, C::poseidon2_perm_B_38_2, C::poseidon2_perm_B_38_3 },
71 { C::poseidon2_perm_B_39_0, C::poseidon2_perm_B_39_1, C::poseidon2_perm_B_39_2, C::poseidon2_perm_B_39_3 },
72 { C::poseidon2_perm_B_40_0, C::poseidon2_perm_B_40_1, C::poseidon2_perm_B_40_2, C::poseidon2_perm_B_40_3 },
73 { C::poseidon2_perm_B_41_0, C::poseidon2_perm_B_41_1, C::poseidon2_perm_B_41_2, C::poseidon2_perm_B_41_3 },
74 { C::poseidon2_perm_B_42_0, C::poseidon2_perm_B_42_1, C::poseidon2_perm_B_42_2, C::poseidon2_perm_B_42_3 },
75 { C::poseidon2_perm_B_43_0, C::poseidon2_perm_B_43_1, C::poseidon2_perm_B_43_2, C::poseidon2_perm_B_43_3 },
76 { C::poseidon2_perm_B_44_0, C::poseidon2_perm_B_44_1, C::poseidon2_perm_B_44_2, C::poseidon2_perm_B_44_3 },
77 { C::poseidon2_perm_B_45_0, C::poseidon2_perm_B_45_1, C::poseidon2_perm_B_45_2, C::poseidon2_perm_B_45_3 },
78 { C::poseidon2_perm_B_46_0, C::poseidon2_perm_B_46_1, C::poseidon2_perm_B_46_2, C::poseidon2_perm_B_46_3 },
79 { C::poseidon2_perm_B_47_0, C::poseidon2_perm_B_47_1, C::poseidon2_perm_B_47_2, C::poseidon2_perm_B_47_3 },
80 { C::poseidon2_perm_B_48_0, C::poseidon2_perm_B_48_1, C::poseidon2_perm_B_48_2, C::poseidon2_perm_B_48_3 },
81 { C::poseidon2_perm_B_49_0, C::poseidon2_perm_B_49_1, C::poseidon2_perm_B_49_2, C::poseidon2_perm_B_49_3 },
82 { C::poseidon2_perm_B_50_0, C::poseidon2_perm_B_50_1, C::poseidon2_perm_B_50_2, C::poseidon2_perm_B_50_3 },
83 { C::poseidon2_perm_B_51_0, C::poseidon2_perm_B_51_1, C::poseidon2_perm_B_51_2, C::poseidon2_perm_B_51_3 },
84 { C::poseidon2_perm_B_52_0, C::poseidon2_perm_B_52_1, C::poseidon2_perm_B_52_2, C::poseidon2_perm_B_52_3 },
85 { C::poseidon2_perm_B_53_0, C::poseidon2_perm_B_53_1, C::poseidon2_perm_B_53_2, C::poseidon2_perm_B_53_3 },
86 { C::poseidon2_perm_B_54_0, C::poseidon2_perm_B_54_1, C::poseidon2_perm_B_54_2, C::poseidon2_perm_B_54_3 },
87 { C::poseidon2_perm_B_55_0, C::poseidon2_perm_B_55_1, C::poseidon2_perm_B_55_2, C::poseidon2_perm_B_55_3 },
88 { C::poseidon2_perm_B_56_0, C::poseidon2_perm_B_56_1, C::poseidon2_perm_B_56_2, C::poseidon2_perm_B_56_3 },
89 { C::poseidon2_perm_B_57_0, C::poseidon2_perm_B_57_1, C::poseidon2_perm_B_57_2, C::poseidon2_perm_B_57_3 },
90 { C::poseidon2_perm_B_58_0, C::poseidon2_perm_B_58_1, C::poseidon2_perm_B_58_2, C::poseidon2_perm_B_58_3 },
91 { C::poseidon2_perm_B_59_0, C::poseidon2_perm_B_59_1, C::poseidon2_perm_B_59_2, C::poseidon2_perm_B_59_3 },
95 { C::poseidon2_perm_T_60_4, C::poseidon2_perm_T_60_5, C::poseidon2_perm_T_60_6, C::poseidon2_perm_T_60_7 },
96 { C::poseidon2_perm_T_61_4, C::poseidon2_perm_T_61_5, C::poseidon2_perm_T_61_6, C::poseidon2_perm_T_61_7 },
97 { C::poseidon2_perm_T_62_4, C::poseidon2_perm_T_62_5, C::poseidon2_perm_T_62_6, C::poseidon2_perm_T_62_7 },
98 { C::poseidon2_perm_T_63_4, C::poseidon2_perm_T_63_5, C::poseidon2_perm_T_63_6, C::poseidon2_perm_T_63_7 },
104 const auto full_round_add_constant = []<
typename T,
typename U>(
std::array<T, 4>& state,
114 state[0] = state[0] * state[0] * state[0] * state[0] * state[0];
115 state[1] = state[1] * state[1] * state[1] * state[1] * state[1];
116 state[2] = state[2] * state[2] * state[2] * state[2] * state[2];
117 state[3] = state[3] * state[3] * state[3] * state[3] * state[3];
122 auto t0 = state[0] + state[1];
123 auto t1 = state[2] + state[3];
124 auto t2 =
FF(2) * state[1] + t1;
125 auto t3 =
FF(2) * state[3] + t0;
126 auto t4 =
FF(4) * t1 + t3;
127 auto t5 =
FF(4) * t0 + t2;
137 const auto partial_round_add_constant = []<
typename T,
typename U>(
std::array<T, 4>& state,
const U& rc) {
143 state[0] = state[0] * state[0] * state[0] * state[0] * state[0];
148 const auto internal_matrix_mul =
151 auto sum = state[0] + state[1] + state[2] + state[3];
152 for (
size_t i = 0; i < 4; ++i) {
153 state[i] = state[i] * internal_matrix_diagonal_minus_one[i] +
sum;
161 using View =
typename std::tuple_element_t<0, ContainerOverSubrelations>::View;
162 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
163 (
FF(1) -
static_cast<View
>(in.get(C::poseidon2_perm_sel)));
168 auto state = std::array{
169 in.get(C::poseidon2_perm_a_0),
170 in.get(C::poseidon2_perm_a_1),
171 in.get(C::poseidon2_perm_a_2),
172 in.get(C::poseidon2_perm_a_3),
184 external_matrix_mul(state);
187 using View =
typename std::tuple_element_t<1, ContainerOverSubrelations>::View;
188 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
189 (
static_cast<View
>(in.get(C::poseidon2_perm_EXT_LAYER_4)) -
CView(state[3]));
193 using View =
typename std::tuple_element_t<2, ContainerOverSubrelations>::View;
194 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
195 (
static_cast<View
>(in.get(C::poseidon2_perm_EXT_LAYER_5)) -
CView(state[1]));
199 using View =
typename std::tuple_element_t<3, ContainerOverSubrelations>::View;
200 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
201 (
static_cast<View
>(in.get(C::poseidon2_perm_EXT_LAYER_6)) -
CView(state[0]));
205 using View =
typename std::tuple_element_t<4, ContainerOverSubrelations>::View;
206 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
207 (
static_cast<View
>(in.get(C::poseidon2_perm_EXT_LAYER_7)) -
CView(state[2]));
212 constexpr size_t START_RELATION_OF_PERM = 5;
216 in.get(C::poseidon2_perm_EXT_LAYER_6),
217 in.get(C::poseidon2_perm_EXT_LAYER_5),
218 in.get(C::poseidon2_perm_EXT_LAYER_7),
219 in.get(C::poseidon2_perm_EXT_LAYER_4),
223 constexpr_for<0, 4, 1>([&]<
size_t i>() {
224 constexpr size_t relation_offset = START_RELATION_OF_PERM + (i * 4);
225 full_round_add_constant(state, Poseidon2Params::round_constants[i]);
226 full_round_s_box(state);
227 external_matrix_mul(state);
230 using View =
typename std::tuple_element_t<relation_offset, ContainerOverSubrelations>::View;
231 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
232 (
static_cast<View
>(in.get(round_cols[i][0])) -
CView(state[3]));
237 using View =
typename std::tuple_element_t<relation_offset + 1, ContainerOverSubrelations>::View;
238 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
239 (
static_cast<View
>(in.get(round_cols[i][1])) -
CView(state[1]));
244 using View =
typename std::tuple_element_t<relation_offset + 2, ContainerOverSubrelations>::View;
245 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
246 (
static_cast<View
>(in.get(round_cols[i][2])) -
CView(state[0]));
251 using View =
typename std::tuple_element_t<relation_offset + 3, ContainerOverSubrelations>::View;
252 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
253 (
static_cast<View
>(in.get(round_cols[i][3])) -
CView(state[2]));
259 in.get(round_cols[i][2]),
260 in.get(round_cols[i][1]),
261 in.get(round_cols[i][3]),
262 in.get(round_cols[i][0]),
267 constexpr_for<4, 60, 1>([&]<
size_t i>() {
268 constexpr size_t relation_offset = START_RELATION_OF_PERM + (i * 4);
269 partial_round_add_constant(state, Poseidon2Params::round_constants[i][0]);
270 partial_round_s_box(state);
271 internal_matrix_mul(state, Poseidon2Params::internal_matrix_diagonal_minus_one);
274 using View =
typename std::tuple_element_t<relation_offset, ContainerOverSubrelations>::View;
275 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
276 (
static_cast<View
>(in.get(round_cols[i][0])) -
CView(state[0]));
281 using View =
typename std::tuple_element_t<relation_offset + 1, ContainerOverSubrelations>::View;
282 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
283 (
static_cast<View
>(in.get(round_cols[i][1])) -
CView(state[1]));
288 using View =
typename std::tuple_element_t<relation_offset + 2, ContainerOverSubrelations>::View;
289 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
290 (
static_cast<View
>(in.get(round_cols[i][2])) -
CView(state[2]));
295 using View =
typename std::tuple_element_t<relation_offset + 3, ContainerOverSubrelations>::View;
296 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
297 (
static_cast<View
>(in.get(round_cols[i][3])) -
CView(state[3]));
303 in.get(round_cols[i][0]),
304 in.get(round_cols[i][1]),
305 in.get(round_cols[i][2]),
306 in.get(round_cols[i][3]),
311 constexpr_for<60, 64, 1>([&]<
size_t i>() {
312 constexpr size_t relation_offset = START_RELATION_OF_PERM + (i * 4);
313 full_round_add_constant(state, Poseidon2Params::round_constants[i]);
314 full_round_s_box(state);
315 external_matrix_mul(state);
318 using View =
typename std::tuple_element_t<relation_offset, ContainerOverSubrelations>::View;
319 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
320 (
static_cast<View
>(in.get(round_cols[i][0])) -
CView(state[3]));
325 using View =
typename std::tuple_element_t<relation_offset + 1, ContainerOverSubrelations>::View;
326 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
327 (
static_cast<View
>(in.get(round_cols[i][1])) -
CView(state[1]));
332 using View =
typename std::tuple_element_t<relation_offset + 2, ContainerOverSubrelations>::View;
333 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
334 (
static_cast<View
>(in.get(round_cols[i][2])) -
CView(state[0]));
339 using View =
typename std::tuple_element_t<relation_offset + 3, ContainerOverSubrelations>::View;
340 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
341 (
static_cast<View
>(in.get(round_cols[i][3])) -
CView(state[2]));
347 in.get(round_cols[i][2]),
348 in.get(round_cols[i][1]),
349 in.get(round_cols[i][3]),
350 in.get(round_cols[i][0]),
356 using View =
typename std::tuple_element_t<261, ContainerOverSubrelations>::View;
358 static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
359 (
static_cast<View
>(in.get(C::poseidon2_perm_b_0)) -
static_cast<View
>(in.get(C::poseidon2_perm_T_63_6)));
363 using View =
typename std::tuple_element_t<262, ContainerOverSubrelations>::View;
365 static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
366 (
static_cast<View
>(in.get(C::poseidon2_perm_b_1)) -
static_cast<View
>(in.get(C::poseidon2_perm_T_63_5)));
370 using View =
typename std::tuple_element_t<263, ContainerOverSubrelations>::View;
372 static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
373 (
static_cast<View
>(in.get(C::poseidon2_perm_b_2)) -
static_cast<View
>(in.get(C::poseidon2_perm_T_63_7)));
377 using View =
typename std::tuple_element_t<264, ContainerOverSubrelations>::View;
379 static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
380 (
static_cast<View
>(in.get(C::poseidon2_perm_b_3)) -
static_cast<View
>(in.get(C::poseidon2_perm_T_63_4)));