26 for (
const auto&
event : events) {
28 uint32_t radix =
event.radix;
29 size_t radix_index =
static_cast<size_t>(radix);
30 uint32_t safe_limbs =
static_cast<uint32_t
>(p_limbs_per_radix[radix_index].size()) - 1;
35 bool acc_under_p =
false;
37 for (uint32_t i = 0; i <
event.limbs.size(); ++i) {
38 bool is_padding = i > safe_limbs;
39 uint8_t limb =
event.limbs[i];
40 uint8_t p_limb = is_padding ? 0 : p_limbs_per_radix[radix_index][
static_cast<size_t>(i)];
43 acc_under_p = limb < p_limb;
45 FF limb_p_diff = limb == p_limb ? 0 : limb > p_limb ? limb - p_limb - 1 : p_limb - limb - 1;
47 bool is_unsafe_limb = i == safe_limbs;
48 FF safety_diff_inverse = is_unsafe_limb ?
FF(0) : (
FF(i) -
FF(safe_limbs)).invert();
50 acc += exponent * limb;
54 FF rem_inverse = found ? 0 : rem.
invert();
56 bool end = i == (
event.limbs.size() - 1);
60 { C::to_radix_sel, 1 },
61 { C::to_radix_value,
value },
62 { C::to_radix_radix, radix },
63 { C::to_radix_limb_index, i },
64 { C::to_radix_limb, limb },
65 { C::to_radix_start, i == 0 },
66 { C::to_radix_end, end },
67 { C::to_radix_not_end, !end },
68 { C::to_radix_exponent, exponent },
69 { C::to_radix_not_padding_limb, !is_padding },
70 { C::to_radix_acc, acc },
71 { C::to_radix_found, found },
72 { C::to_radix_limb_radix_diff, radix - 1 - limb },
73 { C::to_radix_rem_inverse, rem_inverse },
74 { C::to_radix_safe_limbs, safe_limbs },
75 { C::to_radix_is_unsafe_limb, is_unsafe_limb },
76 { C::to_radix_safety_diff_inverse, safety_diff_inverse },
77 { C::to_radix_p_limb, p_limb },
78 { C::to_radix_acc_under_p, acc_under_p },
79 { C::to_radix_limb_lt_p, limb < p_limb },
80 { C::to_radix_limb_eq_p, limb == p_limb },
81 { C::to_radix_limb_p_diff, limb_p_diff },
99 for (
const auto&
event : events) {
102 uint8_t num_limbs_is_zero =
event.limbs.empty() ? 1 : 0;
103 FF num_limbs_inv =
event.limbs.empty() ?
FF(0) :
FF(
event.limbs.size()).invert();
104 uint8_t value_is_zero =
event.value ==
FF(0) ? 1 : 0;
105 FF value_inv =
event.value ==
FF(0) ?
FF(0) :
event.value.invert();
108 uint64_t
dst_addr =
static_cast<uint64_t
>(
event.dst_addr);
109 uint64_t max_write_addr =
dst_addr +
event.limbs.size() - 1;
113 bool invalid_radix = (
event.radix < 2 ||
event.radix > 256);
114 bool invalid_bitwise_radix =
event.is_output_bits &&
event.radix != 2;
117 bool invalid_num_limbs =
event.limbs.empty() && !(
event.value ==
FF(0));
119 if (write_out_of_range || invalid_radix) {
122 { C::to_radix_mem_sel, 1 },
123 { C::to_radix_mem_start, 1 },
124 { C::to_radix_mem_last, 1 },
126 { C::to_radix_mem_execution_clk,
event.execution_clk },
127 { C::to_radix_mem_space_id,
event.space_id },
128 { C::to_radix_mem_dst_addr,
dst_addr },
129 { C::to_radix_mem_value_to_decompose,
event.value },
130 { C::to_radix_mem_radix,
event.radix },
131 { C::to_radix_mem_num_limbs,
static_cast<uint32_t
>(
event.limbs.size()) },
132 { C::to_radix_mem_is_output_bits,
event.is_output_bits ? 1 : 0 },
135 { C::to_radix_mem_max_write_addr, max_write_addr },
136 { C::to_radix_mem_two, 2 },
137 { C::to_radix_mem_two_five_six, 256 },
138 { C::to_radix_mem_sel_num_limbs_is_zero, num_limbs_is_zero },
139 { C::to_radix_mem_num_limbs_inv, num_limbs_inv },
140 { C::to_radix_mem_sel_value_is_zero, value_is_zero },
141 { C::to_radix_mem_value_inv, value_inv },
143 { C::to_radix_mem_sel_dst_out_of_range_err, write_out_of_range },
144 { C::to_radix_mem_sel_radix_lt_2_err,
event.radix < 2 },
145 { C::to_radix_mem_sel_radix_gt_256_err,
event.radix > 256 },
146 { C::to_radix_mem_sel_invalid_bitwise_radix, invalid_bitwise_radix ? 1 : 0 },
147 { C::to_radix_mem_sel_invalid_num_limbs_err, invalid_num_limbs ? 1 : 0 },
148 { C::to_radix_mem_err, 1 },
155 uint32_t num_limbs =
static_cast<uint32_t
>(
event.limbs.size());
156 for (uint32_t i = 0; i <
event.limbs.size(); ++i) {
159 bool last = i == (
event.limbs.size() - 1);
164 { C::to_radix_mem_sel, 1 },
165 { C::to_radix_mem_start, start ? 1 : 0 },
166 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).invert() },
167 { C::to_radix_mem_last, last ? 1 : 0 },
169 { C::to_radix_mem_execution_clk,
event.execution_clk },
170 { C::to_radix_mem_space_id,
event.space_id },
171 { C::to_radix_mem_dst_addr,
dst_addr },
172 { C::to_radix_mem_value_to_decompose,
event.value },
173 { C::to_radix_mem_radix,
event.radix },
174 { C::to_radix_mem_num_limbs, num_limbs },
175 { C::to_radix_mem_is_output_bits,
event.is_output_bits ? 1 : 0 },
178 { C::to_radix_mem_max_write_addr, max_write_addr },
179 { C::to_radix_mem_two, start ? 2 : 0 },
180 { C::to_radix_mem_two_five_six, start ? 256 : 0 },
181 { C::to_radix_mem_sel_num_limbs_is_zero, start ? num_limbs_is_zero : 0 },
182 { C::to_radix_mem_num_limbs_inv, num_limbs_inv },
183 { C::to_radix_mem_sel_value_is_zero, start ? value_is_zero : 0 },
184 { C::to_radix_mem_value_inv, value_inv },
186 { C::to_radix_mem_sel_should_exec, !
event.limbs.empty() ? 1 : 0 },
187 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 1 },
188 { C::to_radix_mem_output_limb_value, limb_value.
as_ff() },
189 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(limb_value.
get_tag()) },