42 [[maybe_unused]]
const FF_& scaling_factor)
55 for (
size_t k = 0; k < 4; ++k) {
60 const auto power_of_5 = []<
typename T>(
const T& x) {
68 for (
auto& x : state) {
76 const auto constrain_external_matrix = [&]<
size_t Index,
typename T>(
const std::array<T, 4>& input,
78 const auto t0 = input[0] + input[1];
79 const auto t1 = input[2] + input[3];
80 const auto t2 =
FF(2) * input[1] + t1;
81 const auto t3 =
FF(2) * input[3] + t0;
82 const auto t4 =
FF(4) * t1 + t3;
83 const auto t5 =
FF(4) * t0 + t2;
84 const auto t6 = t3 + t5;
85 const auto t7 = t2 + t4;
87 using View =
typename std::tuple_element_t<Index + 0, ContainerOverSubrelations>::View;
89 static_cast<View
>(in.get(C::poseidon2_perm_sel)) * (
static_cast<View
>(in.get(
out[0])) -
CView(t4));
93 using View =
typename std::tuple_element_t<Index + 1, ContainerOverSubrelations>::View;
95 static_cast<View
>(in.get(C::poseidon2_perm_sel)) * (
static_cast<View
>(in.get(
out[1])) -
CView(t5));
99 using View =
typename std::tuple_element_t<Index + 2, ContainerOverSubrelations>::View;
101 static_cast<View
>(in.get(C::poseidon2_perm_sel)) * (
static_cast<View
>(in.get(
out[2])) -
CView(t6));
105 using View =
typename std::tuple_element_t<Index + 3, ContainerOverSubrelations>::View;
107 static_cast<View
>(in.get(C::poseidon2_perm_sel)) * (
static_cast<View
>(in.get(
out[3])) -
CView(t7));
116 using View =
typename std::tuple_element_t<0, ContainerOverSubrelations>::View;
117 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
118 (
FF(1) -
static_cast<View
>(in.get(C::poseidon2_perm_sel)));
127 const std::array input = {
128 in.get(C::poseidon2_perm_a_0),
129 in.get(C::poseidon2_perm_a_1),
130 in.get(C::poseidon2_perm_a_2),
131 in.get(C::poseidon2_perm_a_3),
134 C::poseidon2_perm_EXT_LAYER_4,
135 C::poseidon2_perm_EXT_LAYER_5,
136 C::poseidon2_perm_EXT_LAYER_6,
137 C::poseidon2_perm_EXT_LAYER_7,
141 constrain_external_matrix.template operator()<1>(input,
out);
148 constexpr size_t START_RELATION_OF_PERM = 5;
151 { C::poseidon2_perm_EXT_LAYER_6,
152 C::poseidon2_perm_EXT_LAYER_5,
153 C::poseidon2_perm_EXT_LAYER_7,
154 C::poseidon2_perm_EXT_LAYER_4 },
155 { C::poseidon2_perm_T_0_6, C::poseidon2_perm_T_0_5, C::poseidon2_perm_T_0_7, C::poseidon2_perm_T_0_4 },
156 { C::poseidon2_perm_T_1_6, C::poseidon2_perm_T_1_5, C::poseidon2_perm_T_1_7, C::poseidon2_perm_T_1_4 },
157 { C::poseidon2_perm_T_2_6, C::poseidon2_perm_T_2_5, C::poseidon2_perm_T_2_7, C::poseidon2_perm_T_2_4 },
160 { C::poseidon2_perm_T_0_4, C::poseidon2_perm_T_0_5, C::poseidon2_perm_T_0_6, C::poseidon2_perm_T_0_7 },
161 { C::poseidon2_perm_T_1_4, C::poseidon2_perm_T_1_5, C::poseidon2_perm_T_1_6, C::poseidon2_perm_T_1_7 },
162 { C::poseidon2_perm_T_2_4, C::poseidon2_perm_T_2_5, C::poseidon2_perm_T_2_6, C::poseidon2_perm_T_2_7 },
163 { C::poseidon2_perm_T_3_4, C::poseidon2_perm_T_3_5, C::poseidon2_perm_T_3_6, C::poseidon2_perm_T_3_7 },
166 bb::constexpr_for<0, 4, 1>([&]<
size_t I>() {
167 constexpr size_t sub_index_offset = START_RELATION_OF_PERM + (4 * I);
169 in.get(initial_input_cols[I][0]),
170 in.get(initial_input_cols[I][1]),
171 in.get(initial_input_cols[I][2]),
172 in.get(initial_input_cols[I][3]),
174 add_round_constant(state, PParams::round_constants[I]);
176 constrain_external_matrix.template operator()<sub_index_offset>(state, initial_out_cols[I]);
189 const auto poseidon2_perm_B_3_0 = in.get(C::poseidon2_perm_T_3_6);
190 const auto poseidon2_perm_B_3_1 = in.get(C::poseidon2_perm_T_3_5);
191 const auto poseidon2_perm_B_3_2 = in.get(C::poseidon2_perm_T_3_7);
192 const auto poseidon2_perm_B_3_3 = in.get(C::poseidon2_perm_T_3_4);
194 C::poseidon2_perm_B_4_0, C::poseidon2_perm_B_5_0, C::poseidon2_perm_B_6_0, C::poseidon2_perm_B_7_0,
195 C::poseidon2_perm_B_8_0, C::poseidon2_perm_B_9_0, C::poseidon2_perm_B_10_0, C::poseidon2_perm_B_11_0,
196 C::poseidon2_perm_B_12_0, C::poseidon2_perm_B_13_0, C::poseidon2_perm_B_14_0, C::poseidon2_perm_B_15_0,
197 C::poseidon2_perm_B_16_0, C::poseidon2_perm_B_17_0, C::poseidon2_perm_B_18_0, C::poseidon2_perm_B_19_0,
198 C::poseidon2_perm_B_20_0, C::poseidon2_perm_B_21_0, C::poseidon2_perm_B_22_0, C::poseidon2_perm_B_23_0,
199 C::poseidon2_perm_B_24_0, C::poseidon2_perm_B_25_0, C::poseidon2_perm_B_26_0, C::poseidon2_perm_B_27_0,
200 C::poseidon2_perm_B_28_0, C::poseidon2_perm_B_29_0, C::poseidon2_perm_B_30_0, C::poseidon2_perm_B_31_0,
201 C::poseidon2_perm_B_32_0, C::poseidon2_perm_B_33_0, C::poseidon2_perm_B_34_0, C::poseidon2_perm_B_35_0,
202 C::poseidon2_perm_B_36_0, C::poseidon2_perm_B_37_0, C::poseidon2_perm_B_38_0, C::poseidon2_perm_B_39_0,
203 C::poseidon2_perm_B_40_0, C::poseidon2_perm_B_41_0, C::poseidon2_perm_B_42_0, C::poseidon2_perm_B_43_0,
204 C::poseidon2_perm_B_44_0, C::poseidon2_perm_B_45_0, C::poseidon2_perm_B_46_0, C::poseidon2_perm_B_47_0,
205 C::poseidon2_perm_B_48_0, C::poseidon2_perm_B_49_0, C::poseidon2_perm_B_50_0, C::poseidon2_perm_B_51_0,
206 C::poseidon2_perm_B_52_0, C::poseidon2_perm_B_53_0, C::poseidon2_perm_B_54_0, C::poseidon2_perm_B_55_0,
207 C::poseidon2_perm_B_56_0, C::poseidon2_perm_B_57_0, C::poseidon2_perm_B_58_0, C::poseidon2_perm_B_59_0
212 using ChainElem =
std::decay_t<
decltype(in.get(C::poseidon2_perm_T_3_5) * PQuad::D2)>;
219 const auto ark = poseidon2_perm_B_3_0 + PParams::round_constants[4][0];
220 alphas_arr[0] = power_of_5(ark);
221 xs_arrs[0] = poseidon2_perm_B_3_1 * PQuad::D2 + poseidon2_perm_B_3_2 + poseidon2_perm_B_3_3 + alphas_arr[0];
222 ys_arrs[0] = poseidon2_perm_B_3_1 + poseidon2_perm_B_3_2 * PQuad::D3 + poseidon2_perm_B_3_3 + alphas_arr[0];
223 zs_arrs[0] = poseidon2_perm_B_3_1 + poseidon2_perm_B_3_2 + poseidon2_perm_B_3_3 * PQuad::D4 + alphas_arr[0];
226 bb::constexpr_for<1, 56, 1>([&]<
size_t i>() {
227 const auto ark = in.get(B_partial_cols[i - 1]) + PParams::round_constants[i + 4][0];
228 alphas_arr[i] = power_of_5(ark);
229 if constexpr (i < 55) {
230 xs_arrs[i] = xs_arrs[i - 1] * PQuad::D2 + ys_arrs[i - 1] + zs_arrs[i - 1] + alphas_arr[i];
231 ys_arrs[i] = xs_arrs[i - 1] + ys_arrs[i - 1] * PQuad::D3 + zs_arrs[i - 1] + alphas_arr[i];
232 zs_arrs[i] = xs_arrs[i - 1] + ys_arrs[i - 1] + zs_arrs[i - 1] * PQuad::D4 + alphas_arr[i];
237 bb::constexpr_for<0, 56, 1>([&]<
size_t i>() {
238 constexpr size_t PARTIAL_ROUND_SUB_INDEX = 21 + i;
239 using View =
typename std::tuple_element_t<PARTIAL_ROUND_SUB_INDEX, ContainerOverSubrelations>::View;
240 if constexpr (i == 0) {
241 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
242 (
static_cast<View
>(in.get(B_partial_cols[i])) -
243 (
CView(PQuad::D1) *
CView(alphas_arr[i]) +
CView(poseidon2_perm_B_3_1) +
244 CView(poseidon2_perm_B_3_2) +
CView(poseidon2_perm_B_3_3)));
247 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
248 (
static_cast<View
>(in.get(B_partial_cols[i])) -
250 CView(zs_arrs[i - 1])));
256 using View =
typename std::tuple_element_t<77, ContainerOverSubrelations>::View;
258 static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
259 (
static_cast<View
>(in.get(C::poseidon2_perm_B_59_1)) -
264 using View =
typename std::tuple_element_t<78, ContainerOverSubrelations>::View;
266 static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
267 (
static_cast<View
>(in.get(C::poseidon2_perm_B_59_2)) -
272 using View =
typename std::tuple_element_t<79, ContainerOverSubrelations>::View;
274 static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
275 (
static_cast<View
>(in.get(C::poseidon2_perm_B_59_3)) -
286 { C::poseidon2_perm_B_59_0, C::poseidon2_perm_B_59_1, C::poseidon2_perm_B_59_2, C::poseidon2_perm_B_59_3 },
287 { C::poseidon2_perm_T_60_6, C::poseidon2_perm_T_60_5, C::poseidon2_perm_T_60_7, C::poseidon2_perm_T_60_4 },
288 { C::poseidon2_perm_T_61_6, C::poseidon2_perm_T_61_5, C::poseidon2_perm_T_61_7, C::poseidon2_perm_T_61_4 },
289 { C::poseidon2_perm_T_62_6, C::poseidon2_perm_T_62_5, C::poseidon2_perm_T_62_7, C::poseidon2_perm_T_62_4 },
292 { C::poseidon2_perm_T_60_4, C::poseidon2_perm_T_60_5, C::poseidon2_perm_T_60_6, C::poseidon2_perm_T_60_7 },
293 { C::poseidon2_perm_T_61_4, C::poseidon2_perm_T_61_5, C::poseidon2_perm_T_61_6, C::poseidon2_perm_T_61_7 },
294 { C::poseidon2_perm_T_62_4, C::poseidon2_perm_T_62_5, C::poseidon2_perm_T_62_6, C::poseidon2_perm_T_62_7 },
295 { C::poseidon2_perm_T_63_4, C::poseidon2_perm_T_63_5, C::poseidon2_perm_T_63_6, C::poseidon2_perm_T_63_7 },
297 bb::constexpr_for<0, 4, 1>([&]<
size_t I>() {
298 constexpr size_t base = 80 + (4 * I);
300 in.get(final_in_state[I][0]),
301 in.get(final_in_state[I][1]),
302 in.get(final_in_state[I][2]),
303 in.get(final_in_state[I][3]),
305 add_round_constant(state, PParams::round_constants[60 + I]);
307 constrain_external_matrix.template operator()<base>(state, final_out[I]);
315 C::poseidon2_perm_b_0,
316 C::poseidon2_perm_b_1,
317 C::poseidon2_perm_b_2,
318 C::poseidon2_perm_b_3,
321 C::poseidon2_perm_T_63_6,
322 C::poseidon2_perm_T_63_5,
323 C::poseidon2_perm_T_63_7,
324 C::poseidon2_perm_T_63_4,
326 bb::constexpr_for<0, 4, 1>([&]<
size_t I>() {
327 constexpr size_t sub_idx = 96 + I;
328 using View =
typename std::tuple_element_t<sub_idx, ContainerOverSubrelations>::View;
329 auto tmp =
static_cast<View
>(in.get(C::poseidon2_perm_sel)) *
330 (
static_cast<View
>(in.get(output_cols[I])) -
static_cast<View
>(in.get(final_state_cols[I])));