19 size_t input_size = input.size();
21 auto num_perm_events = (input_size / 3) +
static_cast<size_t>(input_size % 3 != 0);
24 intermediate_states.reserve(num_perm_events + 1);
29 std::array<FF, 4> perm_state = { 0, 0, 0, iv };
30 intermediate_states.push_back(perm_state);
35 for (
size_t i = 0; i < num_perm_events; i++) {
37 size_t chunk_size = std::min(input_size,
static_cast<size_t>(3));
39 for (
size_t j = 0; j < chunk_size; j++) {
40 perm_state[j] += input[(i * 3) + j];
43 intermediate_states.push_back(perm_state);
45 input_size -= chunk_size;
49 { .inputs = input, .intermediate_states =
std::move(intermediate_states), .output = perm_state[0] });
63 uint32_t space_id =
memory.get_space_id();
65 auto zero = MemoryValue::from<FF>(0);
73 uint64_t max_read_address =
static_cast<uint64_t
>(src_address) + 3;
74 uint64_t max_write_address =
static_cast<uint64_t
>(dst_address) + 3;
79 if (read_out_of_range || write_out_of_range) {
80 throw std::runtime_error(
"src or dst address out of range");
84 for (uint32_t i = 0; i < 4; i++) {
85 input[i] =
memory.get(src_address + i);
90 if (std::ranges::any_of(
91 input.begin(), input.end(), [](
const MemoryValue& val) { return val.get_tag() != MemoryTag::FF; })) {
92 throw std::runtime_error(
"An input tag is not FF");
104 for (uint32_t i = 0; i < 4; i++) {
108 .execution_clk = execution_clk,
109 .src_address = src_address,
110 .dst_address = dst_address,
114 }
catch (
const std::exception& e) {
116 .execution_clk = execution_clk,
117 .src_address = src_address,
118 .dst_address = dst_address,
120 .output = { 0, 0, 0, 0 } });