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 =
FF(i) -
FF(safe_limbs);
50 acc += exponent * limb;
55 bool end = i == (
event.limbs.size() - 1);
59 { C::to_radix_sel, 1 },
60 { C::to_radix_value,
value },
61 { C::to_radix_radix, radix },
62 { C::to_radix_limb_index, i },
63 { C::to_radix_limb, limb },
64 { C::to_radix_start, i == 0 },
65 { C::to_radix_end, end },
66 { C::to_radix_not_end, !end },
67 { C::to_radix_exponent, exponent },
68 { C::to_radix_not_padding_limb, !is_padding },
69 { C::to_radix_acc, acc },
70 { C::to_radix_found, found },
71 { C::to_radix_limb_radix_diff, radix - 1 - limb },
72 { C::to_radix_rem_inverse, rem },
73 { C::to_radix_safe_limbs, safe_limbs },
74 { C::to_radix_is_unsafe_limb, is_unsafe_limb },
75 { C::to_radix_safety_diff_inverse, safety_diff },
76 { C::to_radix_p_limb, p_limb },
77 { C::to_radix_acc_under_p, acc_under_p },
78 { C::to_radix_limb_lt_p, limb < p_limb },
79 { C::to_radix_limb_eq_p, limb == p_limb },
80 { C::to_radix_limb_p_diff, limb_p_diff },
92 trace.invert_columns({ { C::to_radix_safety_diff_inverse, C::to_radix_rem_inverse } });
101 for (
const auto&
event : events) {
103 uint8_t num_limbs_is_zero =
event.num_limbs == 0 ? 1 : 0;
104 FF num_limbs_inv =
event.num_limbs == 0 ?
FF(0) :
FF(
event.num_limbs);
105 uint8_t value_is_zero =
event.value ==
FF(0) ? 1 : 0;
106 FF value_inv =
event.value ==
FF(0) ?
FF(0) :
event.value;
109 uint64_t
dst_addr =
static_cast<uint64_t
>(
event.dst_addr);
110 uint64_t write_addr_upper_bound =
dst_addr +
event.num_limbs;
114 bool invalid_radix = (
event.radix < 2 ||
event.radix > 256);
115 bool invalid_bitwise_radix =
event.is_output_bits &&
event.radix != 2;
118 bool invalid_num_limbs =
event.num_limbs == 0 && !(
event.value ==
FF(0));
123 { C::to_radix_mem_sel, 1 },
124 { C::to_radix_mem_start, 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,
event.num_limbs },
132 { C::to_radix_mem_is_output_bits,
event.is_output_bits ? 1 : 0 },
134 { C::to_radix_mem_max_mem_size,
static_cast<uint64_t
>(
AVM_MEMORY_SIZE) },
135 { C::to_radix_mem_write_addr_upper_bound, write_addr_upper_bound },
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 },
145 if (write_out_of_range || invalid_radix || invalid_bitwise_radix || invalid_num_limbs) {
148 { C::to_radix_mem_last, 1 },
149 { C::to_radix_mem_input_validation_error, 1 },
150 { C::to_radix_mem_err, 1 },
151 { C::to_radix_mem_sel_dst_out_of_range_err, write_out_of_range },
152 { C::to_radix_mem_sel_radix_lt_2_err,
event.radix < 2 },
153 { C::to_radix_mem_sel_radix_gt_256_err,
event.radix > 256 },
154 { C::to_radix_mem_sel_invalid_bitwise_radix, invalid_bitwise_radix ? 1 : 0 },
155 { C::to_radix_mem_sel_invalid_num_limbs_err, invalid_num_limbs ? 1 : 0 },
166 std::vector<bool> found(
event.limbs.size(),
false);
167 for (
size_t i = 0; i <
event.limbs.size(); ++i) {
169 size_t reverse_index =
event.limbs.size() - i - 1;
170 FF limb_value =
event.limbs[reverse_index].as_ff();
171 acc += exponent * limb_value;
172 exponent *=
event.radix;
173 found[reverse_index] = acc ==
event.value;
177 if (
event.num_limbs == 0) {
180 { C::to_radix_mem_last, 1 },
187 bool truncation_error =
event.num_limbs != 0 && !found.at(0);
189 if (truncation_error) {
192 { C::to_radix_mem_last, 1 },
193 { C::to_radix_mem_err, 1 },
194 { C::to_radix_mem_sel_truncation_error, 1 },
196 { C::to_radix_mem_sel_should_decompose, 1 },
197 { C::to_radix_mem_limb_index_to_lookup,
event.num_limbs - 1 },
198 { C::to_radix_mem_limb_value,
event.limbs.at(0).as_ff() },
199 { C::to_radix_mem_value_found, 0 },
206 uint32_t remaining_limbs =
static_cast<uint32_t
>(
event.num_limbs);
209 for (uint32_t i = 0; i <
event.num_limbs; ++i) {
211 bool last = i == (
event.num_limbs - 1);
215 { C::to_radix_mem_sel, 1 },
216 { C::to_radix_mem_num_limbs, remaining_limbs },
217 { C::to_radix_mem_num_limbs_minus_one_inv,
218 remaining_limbs - 1 == 0 ? 0 :
FF(remaining_limbs - 1) },
219 { C::to_radix_mem_last, last ? 1 : 0 },
221 { C::to_radix_mem_sel_should_decompose, 1 },
222 { C::to_radix_mem_value_to_decompose,
event.value },
223 { C::to_radix_mem_limb_index_to_lookup, remaining_limbs - 1 },
224 { C::to_radix_mem_radix,
event.radix },
225 { C::to_radix_mem_limb_value, limb_value.
as_ff() },
226 { C::to_radix_mem_value_found, found.at(i) ? 1 : 0 },
228 { C::to_radix_mem_sel_should_write_mem, 1 },
229 { C::to_radix_mem_execution_clk,
event.execution_clk },
230 { C::to_radix_mem_space_id,
event.space_id },
231 { C::to_radix_mem_dst_addr,
dst_addr },
232 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(limb_value.
get_tag()) },
233 { C::to_radix_mem_is_output_bits,
event.is_output_bits ? 1 : 0 },
244 trace.invert_columns(
245 { { C::to_radix_mem_num_limbs_inv, C::to_radix_mem_value_inv, C::to_radix_mem_num_limbs_minus_one_inv } });